diff --git a/include/pacemaker.h b/include/pacemaker.h
index 102d75dcc0..4a10889956 100644
--- a/include/pacemaker.h
+++ b/include/pacemaker.h
@@ -1,202 +1,202 @@
 /*
  * Copyright 2019 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PACEMAKER__H
 #  define PACEMAKER__H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 
 /**
  * \file
  * \brief High Level API
  * \ingroup pacemaker
  */
 
 #  include <crm/stonith-ng.h>
 #  include <libxml/tree.h>
 
 /*!
  * \brief Perform a STONITH action.
  *
  * \param[in] st        A connection to the STONITH API.
  * \param[in] target    The node receiving the action.
  * \param[in] action    The action to perform.
  * \param[in] name      Who requested the fence action?
  * \param[in] timeout   How long to wait for the operation to complete (in ms).
  * \param[in] tolerance If a successful action for \p target happened within
  *                      this many ms, return 0 without performing the action
  *                      again.
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_action(stonith_t *st, const char *target, const char *action,
                       const char *name, unsigned int timeout, unsigned int tolerance);
 
 /*!
  * \brief List the fencing operations that have occurred for a specific node.
  *
  * \note If \p xml is not NULL, it will be freed first and the previous
  *       contents lost.
  *
  * \param[in,out] xml       The destination for the result, as an XML tree.
  * \param[in]     st        A connection to the STONITH API.
  * \param[in]     target    The node to get history for.
  * \param[in]     timeout   How long to wait for the operation to complete (in ms).
  * \param[in]     quiet     Suppress most output.
  * \param[in]     verbose   Include additional output.
  * \param[in]     broadcast Gather fencing history from all nodes.
  * \param[in]     cleanup   Clean up fencing history after listing.
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_history(xmlNodePtr *xml, stonith_t *st, char *target,
                        unsigned int timeout, bool quiet, int verbose,
                        bool broadcast, bool cleanup);
 
 /*!
  * \brief List all installed STONITH agents.
  *
  * \note If \p xml is not NULL, it will be freed first and the previous
  *       contents lost.
  *
  * \param[in,out] xml     The destination for the result, as an XML tree.
  * \param[in]     st      A connection to the STONITH API.
  * \param[in]     timeout How long to wait for the operation to complete (in ms).
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_installed(xmlNodePtr *xml, stonith_t *st, unsigned int timeout);
 
 /*!
  * \brief When was a device last fenced?
  *
  * \note If \p xml is not NULL, it will be freed first and the previous
  *       contents lost.
  *
  * \param[in,out] xml       The destination for the result, as an XML tree.
  * \param[in]     target    The node that was fenced.
  * \param[in]     as_nodeid
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_last(xmlNodePtr *xml, const char *target, bool as_nodeid);
 
 /*!
  * \brief List nodes that can be fenced.
  *
  * \note If \p xml is not NULL, it will be freed first and the previous
  *       contents lost.
  *
- * \param[in,out] xml     The destination for the result, as an XML tree.
- * \param[in]     st      A connection to the STONITH API.
- * \param[in]     agent   The agent that can do the fencing.
- * \param[in]     timeout How long to wait for the operation to complete (in ms).
+ * \param[in,out] xml        The destination for the result, as an XML tree
+ * \param[in]     st         A connection to the STONITH API
+ * \param[in]     device_id  Resource ID of fence device to check
+ * \param[in]     timeout    How long to wait for the operation to complete (in ms)
  *
  * \return Standard Pacemaker return code
  */
-int pcmk_fence_list_targets(xmlNodePtr *xml, stonith_t *st, char *agent,
-                            unsigned int timeout);
+int pcmk_fence_list_targets(xmlNodePtr *xml, stonith_t *st,
+                            const char *device_id, unsigned int timeout);
 
 /*!
  * \brief Get metadata for a resource.
  *
  * \note If \p xml is not NULL, it will be freed first and the previous
  *       contents lost.
  *
  * \param[in,out] xml     The destination for the result, as an XML tree.
  * \param[in]     st      A connection to the STONITH API.
  * \param[in]     agent   The fence agent to get metadata for.
  * \param[in]     timeout How long to wait for the operation to complete (in ms).
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_metadata(xmlNodePtr *xml, stonith_t *st, char *agent,
                         unsigned int timeout);
 
 /*!
  * \brief List registered fence devices.
  *
  * \note If \p xml is not NULL, it will be freed first and the previous
  *       contents lost.
  *
  * \param[in,out] xml     The destination for the result, as an XML tree.
  * \param[in]     st      A connection to the STONITH API.
  * \param[in]     target  If not NULL, only return devices that can fence
  *                        this node.
  * \param[in]     timeout How long to wait for the operation to complete (in ms).
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_registered(xmlNodePtr *xml, stonith_t *st, char *target,
                           unsigned int timeout);
 
 /*!
  * \brief Register a fencing level for a specific node, node regex, or attribute.
  *
  * \p target can take three different forms:
  *   - name=value, in which case \p target is an attribute.
  *   - @pattern, in which case \p target is a node regex.
  *   - Otherwise, \p target is a node name.
  *
  * \param[in] st          A connection to the STONITH API.
  * \param[in] target      The object to register a fencing level for.
  * \param[in] fence_level Index number of level to add.
  * \param[in] devices     Devices to use in level.
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_register_level(stonith_t *st, char *target, int fence_level,
                               stonith_key_value_t *devices);
 
 /*!
  * \brief Unregister a fencing level for a specific node, node regex, or attribute.
  *
  * \p target can take three different forms:
  *   - name=value, in which case \p target is an attribute.
  *   - @pattern, in which case \p target is a node regex.
  *   - Otherwise, \p target is a node name.
  *
  * \param[in] st          A connection to the STONITH API.
  * \param[in] target      The object to unregister a fencing level for.
  * \param[in] fence_level Index number of level to remove.
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_unregister_level(stonith_t *st, char *target, int fence_level);
 
 /*!
  * \brief Validate a STONITH device configuration.
  *
  * \note If \p xml is not NULL, it will be freed first and the previous
  *       contents lost.
  *
  * \param[in,out] xml     The destination for the result, as an XML tree.
  * \param[in]     st      A connection to the STONITH API.
  * \param[in]     agent   The agent to validate (for example, "fence_xvm").
  * \param[in]     id      STONITH device ID (may be NULL).
  * \param[in]     params  STONITH device configuration parameters.
  * \param[in]     timeout How long to wait for the operation to complete (in ms).
  *
  * \return Standard Pacemaker return code
  */
 int pcmk_fence_validate(xmlNodePtr *xml, stonith_t *st, const char *agent,
                         const char *id, stonith_key_value_t *params,
                         unsigned int timeout);
 
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/pcmki/pcmki_fence.h b/include/pcmki/pcmki_fence.h
index 94a174d379..1e5e934af0 100644
--- a/include/pcmki/pcmki_fence.h
+++ b/include/pcmki/pcmki_fence.h
@@ -1,223 +1,223 @@
 /*
  * Copyright 2019 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 #ifndef PCMKI_STONITH_H
 #  define PCMKI_STONITH_H
 
 #  include <crm/common/output.h>
 #  include <crm/stonith-ng.h>
 
 /*!
  * \brief Perform a STONITH action.
  *
  * \note This is the internal version of pcmk_fence_action().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \param[in] st        A connection to the STONITH API.
  * \param[in] target    The node receiving the action.
  * \param[in] action    The action to perform.
  * \param[in] name      Who requested the fence action?
  * \param[in] timeout   How long to wait for the operation to complete (in ms).
  * \param[in] tolerance If a successful action for \p target happened within
  *                      this many ms, return 0 without performing the action
  *                      again.
  * \param[in] delay     Apply a fencing delay. Value -1 means disable also any
  *                      static/random fencing delays from pcmk_delay_base/max
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_action(stonith_t *st, const char *target, const char *action,
                        const char *name, unsigned int timeout, unsigned int tolerance,
                        int delay);
 
 /*!
  * \brief List the fencing operations that have occurred for a specific node.
  *
  * \note This is the internal version of pcmk_fence_history().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \note \p out should be initialized with pcmk__output_new() before calling this
  *       function and destroyed with out->finish and pcmk__output_free() before
  *       reusing it with any other functions in this library.
  *
  * \param[in,out] out       The output functions structure.
  * \param[in]     st        A connection to the STONITH API.
  * \param[in]     target    The node to get history for.
  * \param[in]     timeout   How long to wait for the operation to complete (in ms).
  * \param[in]     quiet     Suppress most output.
  * \param[in]     verbose   Include additional output.
  * \param[in]     broadcast Gather fencing history from all nodes.
  * \param[in]     cleanup   Clean up fencing history after listing.
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_history(pcmk__output_t *out, stonith_t *st, char *target,
                         unsigned int timeout, bool quiet, int verbose,
                         bool broadcast, bool cleanup);
 
 /**
  * \brief List all installed STONITH agents.
  *
  * \note This is the internal version of pcmk_fence_installed().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \note \p out should be initialized with pcmk__output_new() before calling this
  *       function and destroyed with out->finish and pcmk__output_free() before
  *       reusing it with any other functions in this library.
  *
  * \param[in,out] out     The output functions structure.
  * \param[in]     st      A connection to the STONITH API.
  * \param[in]     timeout How long to wait for the operation to complete (in ms).
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_installed(pcmk__output_t *out, stonith_t *st, unsigned int timeout);
 
 /*!
  * \brief When was a device last fenced?
  *
  * \note This is the internal version of pcmk_fence_last().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \note \p out should be initialized with pcmk__output_new() before calling this
  *       function and destroyed with out->finish and pcmk__output_free() before
  *       reusing it with any other functions in this library.
  *
  * \param[in,out] out       The output functions structure.
  * \param[in]     target    The node that was fenced.
  * \param[in]     as_nodeid
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_last(pcmk__output_t *out, const char *target, bool as_nodeid);
 
 /*!
  * \brief List nodes that can be fenced.
  *
  * \note This is the internal version of pcmk_fence_list_targets().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \note \p out should be initialized with pcmk__output_new() before calling this
  *       function and destroyed with out->finish and pcmk__output_free() before
  *       reusing it with any other functions in this library.
  *
- * \param[in,out] out     The output functions structure.
- * \param[in]     st      A connection to the STONITH API.
- * \param[in]     agent   The agent that can do the fencing.
- * \param[in]     timeout How long to wait for the operation to complete (in ms).
+ * \param[in,out] out        The output functions structure
+ * \param[in]     st         A connection to the STONITH API
+ * \param[in]     device_id  Resource ID of fence device to check
+ * \param[in]     timeout    How long to wait for the operation to complete (in ms)
  *
  * \return Standard Pacemaker return code
  */
-int pcmk__fence_list_targets(pcmk__output_t *out, stonith_t *st, char *agent,
-                             unsigned int timeout);
+int pcmk__fence_list_targets(pcmk__output_t *out, stonith_t *st,
+                             const char *device_id, unsigned int timeout);
 
 /*!
  * \brief Get metadata for a resource.
  *
  * \note This is the internal version of pcmk_fence_metadata().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \note \p out should be initialized with pcmk__output_new() before calling this
  *       function and destroyed with out->finish and pcmk__output_free() before
  *       reusing it with any other functions in this library.
  *
  * \param[in,out] out     The output functions structure.
  * \param[in]     st      A connection to the STONITH API.
  * \param[in]     agent   The fence agent to get metadata for.
  * \param[in]     timeout How long to wait for the operation to complete (in ms).
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_metadata(pcmk__output_t *out, stonith_t *st, char *agent,
                          unsigned int timeout);
 
 /*!
  * \brief List registered fence devices.
  *
  * \note This is the internal version of pcmk_fence_metadata().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \note \p out should be initialized with pcmk__output_new() before calling this
  *       function and destroyed with out->finish and pcmk__output_free() before
  *       reusing it with any other functions in this library.
  *
  * \param[in,out] out     The output functions structure.
  * \param[in]     st      A connection to the STONITH API.
  * \param[in]     target  If not NULL, only return devices that can fence
  *                        this node.
  * \param[in]     timeout How long to wait for the operation to complete (in ms).
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_registered(pcmk__output_t *out, stonith_t *st, char *target,
                            unsigned int timeout);
 
 /*!
  * \brief Register a fencing level for a specific node, node regex, or attribute.
  *
  * \note This is the internal version of pcmk_fence_register_level().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \p target can take three different forms:
  *   - name=value, in which case \p target is an attribute.
  *   - @pattern, in which case \p target is a node regex.
  *   - Otherwise, \p target is a node name.
  *
  * \param[in] st          A connection to the STONITH API.
  * \param[in] target      The object to register a fencing level for.
  * \param[in] fence_level Index number of level to add.
  * \param[in] devices     Devices to use in level.
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_register_level(stonith_t *st, char *target, int fence_level,
                               stonith_key_value_t *devices);
 
 /*!
  * \brief Unregister a fencing level for a specific node, node regex, or attribute.
  *
  * \note This is the internal version of pcmk_fence_unregister_level().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \p target can take three different forms:
  *   - name=value, in which case \p target is an attribute.
  *   - @pattern, in which case \p target is a node regex.
  *   - Otherwise, \p target is a node name.
  *
  * \param[in] st          A connection to the STONITH API.
  * \param[in] target      The object to unregister a fencing level for.
  * \param[in] fence_level Index number of level to remove.
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_unregister_level(stonith_t *st, char *target, int fence_level);
 
 /**
  * \brief Validate a STONITH device configuration.
  *
  * \note This is the internal version of pcmk_stonith_validate().  External users
  *       of the pacemaker API should use that function instead.
  *
  * \note \p out should be initialized with pcmk__output_new() before calling this
  *       function and destroyed with out->finish and pcmk__output_free() before
  *       reusing it with any other functions in this library.
  *
  * \param[in,out] out     The output functions structure.
  * \param[in]     st      A connection to the STONITH API.
  * \param[in]     agent   The agent to validate (for example, "fence_xvm").
  * \param[in]     id      STONITH device ID (may be NULL).
  * \param[in]     params  STONITH device configuration parameters.
  * \param[in]     timeout How long to wait for the operation to complete (in ms).
  *
  * \return Standard Pacemaker return code
  */
 int pcmk__fence_validate(pcmk__output_t *out, stonith_t *st, const char *agent,
                          const char *id, stonith_key_value_t *params,
                          unsigned int timeout);
 
 #endif
diff --git a/lib/pacemaker/pcmk_fence.c b/lib/pacemaker/pcmk_fence.c
index 2f610a3b22..a20d39d14b 100644
--- a/lib/pacemaker/pcmk_fence.c
+++ b/lib/pacemaker/pcmk_fence.c
@@ -1,499 +1,499 @@
 /*
  * Copyright 2009-2020 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 #include <crm/common/mainloop.h>
 #include <crm/common/output.h>
 #include <crm/common/results.h>
 #include <crm/stonith-ng.h>
 #include <crm/fencing/internal.h>
 #include <glib.h>
 #include <libxml/tree.h>
 #include <pacemaker.h>
 #include <pcmki/pcmki_output.h>
 #include <pcmki/pcmki_fence.h>
 
 static int st_opts = st_opt_sync_call | st_opt_allow_suicide;
 
 static GMainLoop *mainloop = NULL;
 
 static struct {
     stonith_t *st;
     const char *target;
     const char *action;
     char *name;
     unsigned int timeout;
     unsigned int tolerance;
     int delay;
     int rc;
 } async_fence_data;
 
 static int
 handle_level(stonith_t *st, char *target, int fence_level,
              stonith_key_value_t *devices, bool added) {
     char *node = NULL;
     char *pattern = NULL;
     char *name = NULL;
     char *value = NULL;
     int rc = pcmk_rc_ok;
 
     if (target == NULL) {
         // Not really possible, but makes static analysis happy
         return EINVAL;
     }
 
     /* Determine if targeting by attribute, node name pattern or node name */
     value = strchr(target, '=');
     if (value != NULL)  {
         name = target;
         *value++ = '\0';
     } else if (*target == '@') {
         pattern = target + 1;
     } else {
         node = target;
     }
 
     /* Register or unregister level as appropriate */
     if (added) {
         rc = st->cmds->register_level_full(st, st_opts, node, pattern,
                                            name, value, fence_level,
                                            devices);
     } else {
         rc = st->cmds->remove_level_full(st, st_opts, node, pattern,
                                          name, value, fence_level);
     }
 
     return pcmk_legacy2rc(rc);
 }
 
 static void
 notify_callback(stonith_t * st, stonith_event_t * e)
 {
     if (e->result != pcmk_ok) {
         return;
     }
 
     if (safe_str_eq(async_fence_data.target, e->target) &&
         safe_str_eq(async_fence_data.action, e->action)) {
 
         async_fence_data.rc = e->result;
         g_main_loop_quit(mainloop);
     }
 }
 
 static void
 fence_callback(stonith_t * stonith, stonith_callback_data_t * data)
 {
     async_fence_data.rc = data->rc;
 
     g_main_loop_quit(mainloop);
 }
 
 static gboolean
 async_fence_helper(gpointer user_data)
 {
     stonith_t *st = async_fence_data.st;
     int call_id = 0;
     int rc = stonith_api_connect_retry(st, async_fence_data.name, 10);
 
     if (rc != pcmk_ok) {
         fprintf(stderr, "Could not connect to fencer: %s\n", pcmk_strerror(rc));
         g_main_loop_quit(mainloop);
         return TRUE;
     }
 
     st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, notify_callback);
 
     call_id = st->cmds->fence_with_delay(st,
                                          st_opt_allow_suicide,
                                          async_fence_data.target,
                                          async_fence_data.action,
                                          async_fence_data.timeout/1000,
                                          async_fence_data.tolerance/1000,
                                          async_fence_data.delay);
 
     if (call_id < 0) {
         g_main_loop_quit(mainloop);
         return TRUE;
     }
 
     st->cmds->register_callback(st,
                                 call_id,
                                 async_fence_data.timeout/1000,
                                 st_opt_timeout_updates, NULL, "callback", fence_callback);
 
     return TRUE;
 }
 
 int
 pcmk__fence_action(stonith_t *st, const char *target, const char *action,
                    const char *name, unsigned int timeout, unsigned int tolerance,
                    int delay)
 {
     crm_trigger_t *trig;
 
     async_fence_data.st = st;
     async_fence_data.name = strdup(name);
     async_fence_data.target = target;
     async_fence_data.action = action;
     async_fence_data.timeout = timeout;
     async_fence_data.tolerance = tolerance;
     async_fence_data.delay = delay;
     async_fence_data.rc = pcmk_err_generic;
 
     trig = mainloop_add_trigger(G_PRIORITY_HIGH, async_fence_helper, NULL);
     mainloop_set_trigger(trig);
 
     mainloop = g_main_loop_new(NULL, FALSE);
     g_main_loop_run(mainloop);
 
     free(async_fence_data.name);
 
     return pcmk_legacy2rc(async_fence_data.rc);
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_action(stonith_t *st, const char *target, const char *action,
                   const char *name, unsigned int timeout, unsigned int tolerance,
                   int delay)
 {
     return pcmk__fence_action(st, target, action, name, timeout, tolerance, delay);
 }
 #endif
 
 int
 pcmk__fence_history(pcmk__output_t *out, stonith_t *st, char *target,
                     unsigned int timeout, bool quiet, int verbose,
                     bool broadcast, bool cleanup) {
     stonith_history_t *history = NULL, *hp, *latest = NULL;
     int rc = pcmk_rc_ok;
 
     if (!quiet) {
         if (cleanup) {
             out->info(out, "cleaning up fencing-history%s%s",
                       target ? " for node " : "", target ? target : "");
         }
         if (broadcast) {
             out->info(out, "gather fencing-history from all nodes");
         }
     }
 
     rc = st->cmds->history(st, st_opts | (cleanup ? st_opt_cleanup : 0) |
                            (broadcast ? st_opt_broadcast : 0),
                            safe_str_eq(target, "*") ? NULL : target,
                            &history, timeout/1000);
 
     if (cleanup) {
         // Cleanup doesn't return a history list
         stonith_history_free(history);
         return pcmk_legacy2rc(rc);
     }
 
     out->begin_list(out, "event", "events", "Fencing history");
 
     history = stonith__sort_history(history);
     for (hp = history; hp; hp = hp->next) {
         if (hp->state == st_done) {
             latest = hp;
         }
 
         if (quiet || !verbose) {
             continue;
         }
 
         out->message(out, "stonith-event", hp, 1, stonith__later_succeeded(hp, history));
         out->increment_list(out);
     }
 
     if (latest) {
         if (quiet && out->supports_quiet) {
             out->info(out, "%lld", (long long) latest->completed);
         } else if (!verbose) { // already printed if verbose
             out->message(out, "stonith-event", latest, 0, FALSE);
             out->increment_list(out);
         }
     }
 
     out->end_list(out);
 
     stonith_history_free(history);
     return pcmk_legacy2rc(rc);
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_history(xmlNodePtr *xml, stonith_t *st, char *target, unsigned int timeout,
                    bool quiet, int verbose, bool broadcast, bool cleanup) {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     rc = pcmk__fence_history(out, st, target, timeout, quiet, verbose,
                              broadcast, cleanup);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 #endif
 
 int
 pcmk__fence_installed(pcmk__output_t *out, stonith_t *st, unsigned int timeout) {
     stonith_key_value_t *devices = NULL;
     int rc = pcmk_rc_ok;
 
     rc = st->cmds->list_agents(st, st_opt_sync_call, NULL, &devices, timeout/1000);
     /* list_agents returns a negative error code or a positive number of agents. */
     if (rc < 0) {
         return pcmk_legacy2rc(rc);
     }
 
     out->begin_list(out, "fence device", "fence devices", "Installed fence devices");
     for (stonith_key_value_t *dIter = devices; dIter; dIter = dIter->next) {
         out->list_item(out, "device", "%s", dIter->value);
     }
     out->end_list(out);
 
     stonith_key_value_freeall(devices, 1, 1);
     return pcmk_rc_ok;
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_installed(xmlNodePtr *xml, stonith_t *st, unsigned int timeout) {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     rc = pcmk__fence_installed(out, st, timeout);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 #endif
 
 int
 pcmk__fence_last(pcmk__output_t *out, const char *target, bool as_nodeid) {
     time_t when = 0;
 
     if (target == NULL) {
         return pcmk_rc_ok;
     }
 
     if (as_nodeid) {
         when = stonith_api_time(atol(target), NULL, FALSE);
     } else {
         when = stonith_api_time(0, target, FALSE);
     }
 
     return out->message(out, "last-fenced", target, when);
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_last(xmlNodePtr *xml, const char *target, bool as_nodeid) {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     rc = pcmk__fence_last(out, target, as_nodeid);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 #endif
 
 int
-pcmk__fence_list_targets(pcmk__output_t *out, stonith_t *st, char *agent,
-                         unsigned int timeout) {
+pcmk__fence_list_targets(pcmk__output_t *out, stonith_t *st,
+                         const char *device_id, unsigned int timeout) {
     GList *targets = NULL;
     char *lists = NULL;
     int rc = pcmk_rc_ok;
 
-    rc = st->cmds->list(st, st_opts, agent, &lists, timeout/1000);
+    rc = st->cmds->list(st, st_opts, device_id, &lists, timeout/1000);
     if (rc != pcmk_rc_ok) {
         return pcmk_legacy2rc(rc);
     }
 
     targets = stonith__parse_targets(lists);
 
     out->begin_list(out, "fence target", "fence targets", "Fence Targets");
     while (targets != NULL) {
         out->list_item(out, NULL, "%s", (const char *) targets->data);
         targets = targets->next;
     }
     out->end_list(out);
 
     free(lists);
     return rc;
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
-pcmk_fence_list_targets(xmlNodePtr *xml, stonith_t *st, char *agent,
+pcmk_fence_list_targets(xmlNodePtr *xml, stonith_t *st, const char *device_id,
                         unsigned int timeout) {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
-    rc = pcmk__fence_list_targets(out, st, agent, timeout);
+    rc = pcmk__fence_list_targets(out, st, device_id, timeout);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 #endif
 
 int
 pcmk__fence_metadata(pcmk__output_t *out, stonith_t *st, char *agent,
                      unsigned int timeout) {
     char *buffer = NULL;
     int rc = st->cmds->metadata(st, st_opt_sync_call, agent, NULL, &buffer,
                                 timeout/1000);
 
     if (rc != pcmk_rc_ok) {
         return pcmk_legacy2rc(rc);
     }
 
     out->output_xml(out, "metadata", buffer);
     free(buffer);
     return rc;
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_metadata(xmlNodePtr *xml, stonith_t *st, char *agent,
                     unsigned int timeout) {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     rc = pcmk__fence_metadata(out, st, agent, timeout);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 #endif
 
 int
 pcmk__fence_registered(pcmk__output_t *out, stonith_t *st, char *target,
                        unsigned int timeout) {
     stonith_key_value_t *devices = NULL;
     int rc = pcmk_rc_ok;
 
     rc = st->cmds->query(st, st_opts, target, &devices, timeout/1000);
     /* query returns a negative error code or a positive number of results. */
     if (rc < 0) {
         return pcmk_legacy2rc(rc);
     }
 
     out->begin_list(out, "fence device", "fence devices", "Registered fence devices");
     for (stonith_key_value_t *dIter = devices; dIter; dIter = dIter->next) {
         out->list_item(out, "device", "%s", dIter->value);
     }
     out->end_list(out);
 
     stonith_key_value_freeall(devices, 1, 1);
 
     /* Return pcmk_rc_ok here, not the number of results.  Callers probably
      * don't care.
      */
     return pcmk_rc_ok;
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_registered(xmlNodePtr *xml, stonith_t *st, char *target,
                       unsigned int timeout) {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     rc = pcmk__fence_registered(out, st, target, timeout);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 #endif
 
 int
 pcmk__fence_register_level(stonith_t *st, char *target, int fence_level,
                            stonith_key_value_t *devices) {
     return handle_level(st, target, fence_level, devices, true);
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_register_level(stonith_t *st, char *target, int fence_level,
                             stonith_key_value_t *devices) {
     return pcmk__fence_register_level(st, target, fence_level, devices);
 }
 #endif
 
 int
 pcmk__fence_unregister_level(stonith_t *st, char *target, int fence_level) {
     return handle_level(st, target, fence_level, NULL, false);
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_unregister_level(stonith_t *st, char *target, int fence_level) {
     return pcmk__fence_unregister_level(st, target, fence_level);
 }
 #endif
 
 int
 pcmk__fence_validate(pcmk__output_t *out, stonith_t *st, const char *agent,
                      const char *id, stonith_key_value_t *params,
                      unsigned int timeout) {
     char *output = NULL;
     char *error_output = NULL;
     int rc;
 
     rc  = st->cmds->validate(st, st_opt_sync_call, id, NULL, agent, params,
                              timeout/1000, &output, &error_output);
     out->message(out, "validate", agent, id, output, error_output, rc);
     return pcmk_legacy2rc(rc);
 }
 
 #ifdef BUILD_PUBLIC_LIBPACEMAKER
 int
 pcmk_fence_validate(xmlNodePtr *xml, stonith_t *st, const char *agent,
                     const char *id, stonith_key_value_t *params,
                     unsigned int timeout) {
     pcmk__output_t *out = NULL;
     int rc = pcmk_rc_ok;
 
     rc = pcmk__out_prologue(&out, xml);
     if (rc != pcmk_rc_ok) {
         return rc;
     }
 
     rc = pcmk__fence_validate(out, st, agent, id, params, timeout);
     pcmk__out_epilogue(out, xml, rc);
     return rc;
 }
 #endif
diff --git a/tools/stonith_admin.c b/tools/stonith_admin.c
index 1273a57819..34dc82bfb7 100644
--- a/tools/stonith_admin.c
+++ b/tools/stonith_admin.c
@@ -1,631 +1,631 @@
 /*
  * Copyright 2009-2020 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <sys/utsname.h>
 
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/cluster/internal.h>
 #include <crm/common/cmdline_internal.h>
 #include <crm/common/output.h>
 
 #include <crm/stonith-ng.h>
 #include <crm/fencing/internal.h>
 #include <crm/cib.h>
 #include <crm/pengine/status.h>
 
 #include <crm/common/xml.h>
 #include <pacemaker-internal.h>
 
 #define SUMMARY "stonith_admin - Access the Pacemaker fencing API"
 
 char action = 0;
 
 struct {
     gboolean as_nodeid;
     gboolean broadcast;
     gboolean cleanup;
     gboolean installed;
     gboolean metadata;
     gboolean registered;
     gboolean validate_cfg;
     stonith_key_value_t *devices;
     stonith_key_value_t *params;
     int fence_level;
     int timeout ;
     int tolerance;
     int delay;
     char *agent;
     char *confirm_host;
     char *fence_host;
     char *history;
     char *last_fenced;
     char *query;
     char *reboot_host;
     char *register_dev;
     char *register_level;
     char *targets;
     char *terminate;
     char *unfence_host;
     char *unregister_dev;
     char *unregister_level;
 } options = {
     .timeout = 120,
     .delay = 0
 };
 
 gboolean add_env_params(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean add_stonith_device(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean add_stonith_params(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean add_tolerance(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean set_tag(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 
 #define INDENT "                                    "
 
 /* *INDENT-OFF* */
 static GOptionEntry defn_entries[] = {
     { "register", 'R', 0, G_OPTION_ARG_STRING, &options.register_dev,
       "Register the named stonith device. Requires: --agent.\n"
       INDENT "Optional: --option, --env-option.",
       "DEVICE" },
     { "deregister", 'D', 0, G_OPTION_ARG_STRING, &options.unregister_dev,
       "De-register the named stonith device.",
       "DEVICE" },
     { "register-level", 'r', 0, G_OPTION_ARG_STRING, &options.register_level,
       "Register a stonith level for the named target,\n"
       INDENT "specified as one of NAME, @PATTERN, or ATTR=VALUE.\n"
       INDENT "Requires: --index and one or more --device entries.",
       "TARGET" },
     { "deregister-level", 'd', 0, G_OPTION_ARG_STRING, &options.unregister_level,
       "Unregister a stonith level for the named target,\n"
       INDENT "specified as for --register-level. Requires: --index",
       "TARGET" },
 
     { NULL }
 };
 
 static GOptionEntry query_entries[] = {
     { "list", 'l', 0, G_OPTION_ARG_STRING, &options.terminate,
       "List devices that can terminate the specified host.\n"
       INDENT "Optional: --timeout",
       "HOST" },
     { "list-registered", 'L', 0, G_OPTION_ARG_NONE, &options.registered,
       "List all registered devices. Optional: --timeout.",
       NULL },
     { "list-installed", 'I', 0, G_OPTION_ARG_NONE, &options.installed,
       "List all installed devices. Optional: --timeout.",
       NULL },
     { "list-targets", 's', 0, G_OPTION_ARG_STRING, &options.targets,
       "List the targets that can be fenced by the\n"
       INDENT "named device. Optional: --timeout.",
       "DEVICE" },
     { "metadata", 'M', 0, G_OPTION_ARG_NONE, &options.metadata,
       "Show agent metadata. Requires: --agent.\n"
       INDENT "Optional: --timeout.",
       NULL },
     { "query", 'Q', 0, G_OPTION_ARG_STRING, &options.query,
       "Check the named device's status. Optional: --timeout.",
       "DEVICE" },
     { "history", 'H', 0, G_OPTION_ARG_STRING, &options.history,
       "Show last successful fencing operation for named node\n"
       INDENT "(or '*' for all nodes). Optional: --timeout, --cleanup,\n"
       INDENT "--quiet (show only the operation's epoch timestamp),\n"
       INDENT "--verbose (show all recorded and pending operations),\n"
       INDENT "--broadcast (update history from all nodes available).",
       "NODE" },
     { "last", 'h', 0, G_OPTION_ARG_STRING, &options.last_fenced,
       "Indicate when the named node was last fenced.\n"
       INDENT "Optional: --as-node-id.",
       "NODE" },
     { "validate", 'K', 0, G_OPTION_ARG_NONE, &options.validate_cfg,
       "Validate a fence device configuration.\n"
       INDENT "Requires: --agent. Optional: --option, --env-option,\n"
       INDENT "--quiet (print no output, only return status).",
       NULL },
 
     { NULL }
 };
 
 static GOptionEntry fence_entries[] = {
     { "fence", 'F', 0, G_OPTION_ARG_STRING, &options.fence_host,
       "Fence named host. Optional: --timeout, --tolerance, --delay.",
       "HOST" },
     { "unfence", 'U', 0, G_OPTION_ARG_STRING, &options.unfence_host,
       "Unfence named host. Optional: --timeout, --tolerance, --delay.",
       "HOST" },
     { "reboot", 'B', 0, G_OPTION_ARG_STRING, &options.reboot_host,
       "Reboot named host. Optional: --timeout, --tolerance, --delay.",
       "HOST" },
     { "confirm", 'C', 0, G_OPTION_ARG_STRING, &options.confirm_host,
       "Tell cluster that named host is now safely down.",
       "HOST", },
 
     { NULL }
 };
 
 static GOptionEntry addl_entries[] = {
     { "cleanup", 'c', 0, G_OPTION_ARG_NONE, &options.cleanup,
       "Cleanup wherever appropriate. Requires --history.",
       NULL },
     { "broadcast", 'b', 0, G_OPTION_ARG_NONE, &options.broadcast,
       "Broadcast wherever appropriate.",
       NULL },
     { "agent", 'a', 0, G_OPTION_ARG_STRING, &options.agent,
       "The agent to use (for example, fence_xvm;\n"
       INDENT "with --register, --metadata, --validate).",
       "AGENT" },
     { "option", 'o', 0, G_OPTION_ARG_CALLBACK, add_stonith_params,
       "Specify a device configuration parameter as NAME=VALUE\n"
       INDENT "(may be specified multiple times; with --register,\n"
       INDENT "--validate).",
       "PARAM" },
     { "env-option", 'e', 0, G_OPTION_ARG_CALLBACK, add_env_params,
       "Specify a device configuration parameter with the\n"
       INDENT "specified name, using the value of the\n"
       INDENT "environment variable of the same name prefixed with\n"
       INDENT "OCF_RESKEY_ (may be specified multiple times;\n"
       INDENT "with --register, --validate).",
       "PARAM" },
     { "tag", 'T', 0, G_OPTION_ARG_CALLBACK, set_tag,
       "Identify fencing operations in logs with the specified\n"
       INDENT "tag; useful when multiple entities might invoke\n"
       INDENT "stonith_admin (used with most commands).",
       "TAG" },
     { "device", 'v', 0, G_OPTION_ARG_CALLBACK, add_stonith_device,
       "Device ID (with --register-level, device to associate with\n"
       INDENT "a given host and level; may be specified multiple times)"
 #if SUPPORT_CIBSECRETS
       "\n" INDENT "(with --validate, name to use to load CIB secrets)"
 #endif
       ".",
       "DEVICE" },
     { "index", 'i', 0, G_OPTION_ARG_INT, &options.fence_level,
       "The stonith level (1-9) (with --register-level,\n"
       INDENT "--deregister-level).",
       "LEVEL" },
     { "timeout", 't', 0, G_OPTION_ARG_INT, &options.timeout,
       "Operation timeout in seconds (default 120;\n"
       INDENT "used with most commands).",
       "SECONDS" },
     { "delay", 'y', 0, G_OPTION_ARG_INT, &options.delay,
       "Apply a fencing delay in seconds. Any static/random delays from\n"
       INDENT "pcmk_delay_base/max will be added, otherwise all\n"
       INDENT "disabled with the value -1\n"
       INDENT "(default 0; with --fence, --reboot, --unfence).",
       "SECONDS" },
     { "as-node-id", 'n', 0, G_OPTION_ARG_NONE, &options.as_nodeid,
       "(Advanced) The supplied node is the corosync node ID\n"
       INDENT "(with --last).",
       NULL },
     { "tolerance", 0, 0, G_OPTION_ARG_CALLBACK, add_tolerance,
       "(Advanced) Do nothing if an equivalent --fence request\n"
       INDENT "succeeded less than this many seconds earlier\n"
       INDENT "(with --fence, --unfence, --reboot).",
       "SECONDS" },
 
     { NULL }
 };
 /* *INDENT-ON* */
 
 static pcmk__supported_format_t formats[] = {
     PCMK__SUPPORTED_FORMAT_HTML,
     PCMK__SUPPORTED_FORMAT_TEXT,
     PCMK__SUPPORTED_FORMAT_XML,
     { NULL, NULL, NULL }
 };
 
 static int st_opts = st_opt_sync_call | st_opt_allow_suicide;
 
 static char *name = NULL;
 
 gboolean
 add_env_params(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     char *key = crm_strdup_printf("OCF_RESKEY_%s", optarg);
     const char *env = getenv(key);
     gboolean retval = TRUE;
 
     if (env == NULL) {
         crm_err("Invalid option: -e %s", optarg);
         g_set_error(error, G_OPTION_ERROR, CRM_EX_INVALID_PARAM, "Invalid option: -e %s", optarg);
         retval = FALSE;
     } else {
         crm_info("Got: '%s'='%s'", optarg, env);
         options.params = stonith_key_value_add(options.params, optarg, env);
     }
 
     free(key);
     return retval;
 }
 
 gboolean
 add_stonith_device(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     options.devices = stonith_key_value_add(options.devices, NULL, optarg);
     return TRUE;
 }
 
 gboolean
 add_tolerance(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     options.tolerance = crm_get_msec(optarg) / 1000;
     return TRUE;
 }
 
 gboolean
 add_stonith_params(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     char *name = NULL;
     char *value = NULL;
     int rc = 0;
     gboolean retval = TRUE;
 
     crm_info("Scanning: -o %s", optarg);
 
     rc = pcmk_scan_nvpair(optarg, &name, &value);
 
     if (rc != 2) {
         crm_err("Invalid option: -o %s: %s", optarg, pcmk_strerror(rc));
         g_set_error(error, G_OPTION_ERROR, rc, "Invalid option: -o %s: %s", optarg, pcmk_strerror(rc));
         retval = FALSE;
     } else {
         crm_info("Got: '%s'='%s'", name, value);
         options.params = stonith_key_value_add(options.params, name, value);
     }
 
     free(name);
     free(value);
     return retval;
 }
 
 gboolean
 set_tag(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     free(name);
     name = crm_strdup_printf("%s.%s", crm_system_name, optarg);
     return TRUE;
 }
 
 static GOptionContext *
 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
     GOptionContext *context = NULL;
 
     GOptionEntry extra_prog_entries[] = {
         { "quiet", 'q', 0, G_OPTION_ARG_NONE, &(args->quiet),
           "Be less descriptive in output.",
           NULL },
 
         { NULL }
     };
 
     context = pcmk__build_arg_context(args, "text (default), html, xml", group, NULL);
 
     /* Add the -q option, which cannot be part of the globally supported options
      * because some tools use that flag for something else.
      */
     pcmk__add_main_args(context, extra_prog_entries);
 
     pcmk__add_arg_group(context, "definition", "Device Definition Commands:",
                         "Show device definition help", defn_entries);
     pcmk__add_arg_group(context, "queries", "Queries:",
                         "Show query help", query_entries);
     pcmk__add_arg_group(context, "fence", "Fencing Commands:",
                         "Show fence help", fence_entries);
     pcmk__add_arg_group(context, "additional", "Additional Options:",
                         "Show additional options", addl_entries);
     return context;
 }
 
 int
 main(int argc, char **argv)
 {
     int rc = 0;
     bool no_connect = false;
     bool required_agent = false;
 
     char *target = NULL;
     const char *device = NULL;
 
     crm_exit_t exit_code = CRM_EX_OK;
     stonith_t *st = NULL;
 
     pcmk__output_t *out = NULL;
     pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
 
     GError *error = NULL;
     GOptionContext *context = NULL;
     GOptionGroup *output_group = NULL;
     gchar **processed_args = NULL;
 
     context = build_arg_context(args, &output_group);
     pcmk__register_formats(output_group, formats);
 
     crm_log_cli_init("stonith_admin");
 
     name = strdup(crm_system_name);
 
     processed_args = pcmk__cmdline_preproc(argv, "adehilorstvBCDFHQRTU");
 
     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
         fprintf(stderr, "%s: %s\n", g_get_prgname(), error->message);
         exit_code = CRM_EX_USAGE;
         goto done;
     }
 
     for (int i = 0; i < args->verbosity; i++) {
         crm_bump_log_level(argc, argv);
     }
 
     rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
     if (rc != pcmk_rc_ok) {
         fprintf(stderr, "Error creating output format %s: %s\n",
                 args->output_ty, pcmk_rc_str(rc));
         exit_code = CRM_EX_ERROR;
         goto done;
     }
 
     stonith__register_messages(out);
 
     if (args->version) {
         out->version(out, false);
         goto done;
     }
 
     if (options.validate_cfg) {
         required_agent = true;
         no_connect = true;
         action = 'K';
     }
 
     if (options.installed) {
         no_connect = true;
         action = 'I';
     }
 
     if (options.registered) {
         action = 'L';
     }
 
     if (options.register_dev != NULL) {
         required_agent = true;
         action = 'R';
         device = options.register_dev;
     }
 
     if (options.query != NULL) {
         action = 'Q';
         device = options.query;
     }
 
     if (options.unregister_dev != NULL) {
         action = 'D';
         device = options.unregister_dev;
     }
 
     if (options.targets != NULL) {
         action = 's';
         device = options.targets;
     }
 
     if (options.terminate != NULL) {
         action = 'L';
         target = options.terminate;
     }
 
     if (options.metadata) {
         no_connect = true;
         required_agent = true;
         action = 'M';
     }
 
     if (options.reboot_host != NULL) {
         no_connect = true;
         action = 'B';
         target = options.reboot_host;
         crm_log_args(argc, argv);
     }
 
     if (options.fence_host != NULL) {
         no_connect = true;
         action = 'F';
         target = options.fence_host;
         crm_log_args(argc, argv);
     }
 
     if (options.unfence_host != NULL) {
         no_connect = true;
         action = 'U';
         target = options.unfence_host;
         crm_log_args(argc, argv);
     }
 
     if (options.confirm_host != NULL) {
         action = 'C';
         target = options.confirm_host;
         crm_log_args(argc, argv);
     }
 
     if (options.last_fenced != NULL) {
         action = 'h';
         target = options.last_fenced;
     }
 
     if (options.history != NULL) {
         action = 'H';
         target = options.history;
     }
 
     if (options.register_level != NULL) {
         action = 'r';
         target = options.register_level;
     }
 
     if (options.unregister_level != NULL) {
         action = 'd';
         target = options.unregister_level;
     }
 
     if (optind > argc || action == 0) {
         char *help = g_option_context_get_help(context, TRUE, NULL);
 
         out->err(out, "%s", help);
         g_free(help);
         exit_code = CRM_EX_USAGE;
         goto done;
     }
 
     if (required_agent && options.agent == NULL) {
         char *help = g_option_context_get_help(context, TRUE, NULL);
 
         out->err(out, "Please specify an agent to query using -a,--agent [value]");
         out->err(out, "%s", help);
         g_free(help);
         exit_code = CRM_EX_USAGE;
         goto done;
     }
 
     st = stonith_api_new();
     if (st == NULL) {
         rc = -ENOMEM;
     } else if (!no_connect) {
         rc = st->cmds->connect(st, name, NULL);
     }
     if (rc < 0) {
         out->err(out, "Could not connect to fencer: %s", pcmk_strerror(rc));
         exit_code = CRM_EX_DISCONNECT;
         goto done;
     }
 
     switch (action) {
         case 'I':
             rc = pcmk__fence_installed(out, st, options.timeout*1000);
             if (rc != pcmk_rc_ok) {
                 out->err(out, "Failed to list installed devices: %s", pcmk_strerror(rc));
             }
 
             break;
 
         case 'L':
             rc = pcmk__fence_registered(out, st, target, options.timeout*1000);
             if (rc != pcmk_rc_ok) {
                 out->err(out, "Failed to list registered devices: %s", pcmk_strerror(rc));
             }
 
             break;
 
         case 'Q':
             rc = st->cmds->monitor(st, st_opts, device, options.timeout);
             if (rc != pcmk_rc_ok) {
                 rc = st->cmds->list(st, st_opts, device, NULL, options.timeout);
             }
             rc = pcmk_legacy2rc(rc);
             break;
 
         case 's':
-            rc = pcmk__fence_list_targets(out, st, target, options.timeout*1000);
+            rc = pcmk__fence_list_targets(out, st, device, options.timeout*1000);
             if (rc != pcmk_rc_ok) {
                 out->err(out, "Couldn't list targets: %s", pcmk_strerror(rc));
             }
 
             break;
 
         case 'R':
             rc = st->cmds->register_device(st, st_opts, device, NULL, options.agent,
                                            options.params);
             rc = pcmk_legacy2rc(rc);
             break;
 
         case 'D':
             rc = st->cmds->remove_device(st, st_opts, device);
             rc = pcmk_legacy2rc(rc);
             break;
 
         case 'd':
             rc = pcmk__fence_unregister_level(st, target, options.fence_level);
             break;
 
         case 'r':
             rc = pcmk__fence_register_level(st, target, options.fence_level, options.devices);
             break;
 
         case 'M':
             rc = pcmk__fence_metadata(out, st, options.agent, options.timeout*1000);
             if (rc != pcmk_rc_ok) {
                 out->err(out, "Can't get fence agent meta-data: %s", pcmk_strerror(rc));
             }
 
             break;
 
         case 'C':
             rc = st->cmds->confirm(st, st_opts, target);
             rc = pcmk_legacy2rc(rc);
             break;
 
         case 'B':
             rc = pcmk__fence_action(st, target, "reboot", name, options.timeout*1000,
                                     options.tolerance*1000, options.delay);
             break;
 
         case 'F':
             rc = pcmk__fence_action(st, target, "off", name, options.timeout*1000,
                                     options.tolerance*1000, options.delay);
             break;
 
         case 'U':
             rc = pcmk__fence_action(st, target, "on", name, options.timeout*1000,
                                     options.tolerance*1000, options.delay);
             break;
 
         case 'h':
             rc = pcmk__fence_last(out, target, options.as_nodeid);
             break;
 
         case 'H':
             rc = pcmk__fence_history(out, st, target, options.timeout*1000, args->quiet,
                                        args->verbosity, options.broadcast, options.cleanup);
             break;
 
         case 'K':
             device = options.devices ? options.devices->key : NULL;
             rc = pcmk__fence_validate(out, st, options.agent, device, options.params,
                                         options.timeout*1000);
             break;
     }
 
     crm_info("Command returned: %s (%d)", pcmk_rc_str(rc), rc);
     exit_code = pcmk_rc2exitc(rc);
 
   done:
     g_strfreev(processed_args);
     g_clear_error(&error);
     pcmk__free_arg_context(context);
 
     if (out != NULL) {
         out->finish(out, exit_code, true, NULL);
         pcmk__output_free(out);
     }
     free(name);
     stonith_key_value_freeall(options.params, 1, 1);
 
     if (st != NULL) {
         st->cmds->disconnect(st);
         stonith_api_delete(st);
     }
 
     return exit_code;
 }