diff --git a/etc/devices/ipmipower.dev b/etc/devices/ipmipower.dev index b631de31..4c7319b2 100644 --- a/etc/devices/ipmipower.dev +++ b/etc/devices/ipmipower.dev @@ -30,8 +30,8 @@ specification "ipmipower" { script logout { send "quit\n" } - script status_all { - send "stat\n" + script status_ranged { + send "stat %s\n" foreachnode { expect "([^\n:]+): ([^\n]+\n)" setplugstate $1 $2 on="^on\n" off="^off\n" diff --git a/man/powerman.dev.5.in b/man/powerman.dev.5.in index 96ac62ba..5cd41092 100644 --- a/man/powerman.dev.5.in +++ b/man/powerman.dev.5.in @@ -80,19 +80,17 @@ Executed prior to disconnect. Get device in a state so login script will work (though hopefully disconnecting will do that too). .TP -.I "status_all, status[%s]" -Obtain plug state for all plugs or only the specified plug. -When all plugs of a device are involved in a plug status query, -the status_all script, if defined, will be called in preference to the -status script; otherwise the status script is called for each plug. +.I "status_all, status_ranged[%s], status[%s]" +Obtain plug state for all plugs, a range of plugs, or only the +specified plug. .TP -.I "on_all, on_range[%s], on[%s]" +.I "on_all, on_ranged[%s], on[%s]" Power on all plugs, a range of plugs, or the specified plug. .TP -.I "off_all, off_range[%s], off[%s]" +.I "off_all, off_ranged[%s], off[%s]" Power off all plugs, a range of plugs, or the specified plug. .TP -.I "cycle_all, cycle_range[%s], cycle[%s]" +.I "cycle_all, cycle_ranged[%s], cycle[%s]" Power cycle all plugs, a range of plugs, or the specified plug. The intent of this command was to map to the RPC's cycle command; however, device script are increasingly implementing this in terms of @@ -122,7 +120,7 @@ Flash beacon on the specified plug. .I "beacon_off[%s]" Clear beacon on the specified plug. .TP -.I "reset_all, reset_range[%s], reset[%s]" +.I "reset_all, reset_ranged[%s], reset[%s]" Reset all plugs, a range of plugs, or only the specified plug. Reset refers to signaling a motherboard reset butten header, not a plug cycle. .LP diff --git a/src/powerman/device.c b/src/powerman/device.c index 067d31ba..8228ec52 100644 --- a/src/powerman/device.c +++ b/src/powerman/device.c @@ -78,6 +78,7 @@ typedef struct { ListIterator stmtitr; /* next stmt in block */ Stmt *cur; /* current stmt */ PlugListIterator plugitr; /* used by foreach */ + PlugList pluglist; /* pluglist if foreach is ranged */ bool processing; /* flag used by stmts, ifon/ifoff */ } ExecCtx; @@ -229,6 +230,8 @@ static void _destroy_exec_ctx(ExecCtx *e) e->cur = NULL; if (e->plugs) list_destroy(e->plugs); + if (e->pluglist) + pluglist_destroy(e->pluglist); e->plugs = NULL; xfree(e); } @@ -596,6 +599,10 @@ static int _get_ranged_script(Device * dev, int com) if (dev->scripts[PM_RESET_RANGED]) new = PM_RESET_RANGED; break; + case PM_STATUS_PLUGS: + if (dev->scripts[PM_STATUS_PLUGS_RANGED]) + new = PM_STATUS_PLUGS_RANGED; + break; case PM_BEACON_ON: if (dev->scripts[PM_BEACON_ON_RANGED]) new = PM_BEACON_ON_RANGED; @@ -937,8 +944,18 @@ static bool _process_foreach(Device *dev, Action *act, ExecCtx *e) Plug *plug = NULL; /* we store a plug iterator in the ExecCtx */ - if (e->plugitr == NULL) - e->plugitr = pluglist_iterator_create(dev->plugs); + if (e->plugitr == NULL) { + if (act->com == PM_STATUS_PLUGS_RANGED) { + assert(e->plugs); + if (!e->pluglist) { + if (!(e->pluglist = pluglist_copy_from_list(e->plugs))) + goto cleanup; + } + e->plugitr = pluglist_iterator_create(e->pluglist); + } + else + e->plugitr = pluglist_iterator_create(dev->plugs); + } /* Each time the inner block is executed, its argument will be * a new plug name. Pick that up here. diff --git a/src/powerman/device_private.h b/src/powerman/device_private.h index 6bbe617e..eb1d1416 100644 --- a/src/powerman/device_private.h +++ b/src/powerman/device_private.h @@ -14,35 +14,35 @@ #define NO_FD (-1) /* Indices into script array */ -#define PM_LOG_IN 0 -#define PM_LOG_OUT 1 -#define PM_STATUS_PLUGS 2 -#define PM_STATUS_PLUGS_ALL 3 -/*4*/ +#define PM_LOG_IN 0 +#define PM_LOG_OUT 1 +#define PM_STATUS_PLUGS 2 +#define PM_STATUS_PLUGS_RANGED 3 +#define PM_STATUS_PLUGS_ALL 4 /*5*/ -#define PM_PING 6 -#define PM_POWER_ON 7 -#define PM_POWER_ON_RANGED 8 -#define PM_POWER_ON_ALL 9 -#define PM_POWER_OFF 10 -#define PM_POWER_OFF_RANGED 11 -#define PM_POWER_OFF_ALL 12 -#define PM_POWER_CYCLE 13 -#define PM_POWER_CYCLE_RANGED 14 -#define PM_POWER_CYCLE_ALL 15 -#define PM_RESET 16 -#define PM_RESET_RANGED 17 -#define PM_RESET_ALL 18 -#define PM_STATUS_TEMP 19 -#define PM_STATUS_TEMP_ALL 20 -#define PM_STATUS_BEACON 21 -#define PM_STATUS_BEACON_ALL 22 -#define PM_BEACON_ON 23 -#define PM_BEACON_ON_RANGED 24 -#define PM_BEACON_OFF 25 -#define PM_BEACON_OFF_RANGED 26 -#define PM_RESOLVE 27 -#define NUM_SCRIPTS 28 /* count of scripts above */ +#define PM_PING 6 +#define PM_POWER_ON 7 +#define PM_POWER_ON_RANGED 8 +#define PM_POWER_ON_ALL 9 +#define PM_POWER_OFF 10 +#define PM_POWER_OFF_RANGED 11 +#define PM_POWER_OFF_ALL 12 +#define PM_POWER_CYCLE 13 +#define PM_POWER_CYCLE_RANGED 14 +#define PM_POWER_CYCLE_ALL 15 +#define PM_RESET 16 +#define PM_RESET_RANGED 17 +#define PM_RESET_ALL 18 +#define PM_STATUS_TEMP 19 +#define PM_STATUS_TEMP_ALL 20 +#define PM_STATUS_BEACON 21 +#define PM_STATUS_BEACON_ALL 22 +#define PM_BEACON_ON 23 +#define PM_BEACON_ON_RANGED 24 +#define PM_BEACON_OFF 25 +#define PM_BEACON_OFF_RANGED 26 +#define PM_RESOLVE 27 +#define NUM_SCRIPTS 28 /* count of scripts above */ #define MAX_MATCH_POS 20 diff --git a/src/powerman/parse_lex.l b/src/powerman/parse_lex.l index 2570d40c..9b2c779d 100644 --- a/src/powerman/parse_lex.l +++ b/src/powerman/parse_lex.l @@ -142,6 +142,7 @@ delay return TOK_DELAY; login return TOK_LOGIN; logout return TOK_LOGOUT; status return TOK_STATUS; +status_ranged return TOK_STATUS_RANGED; status_all return TOK_STATUS_ALL; on return TOK_ON; on_ranged return TOK_ON_RANGED; diff --git a/src/powerman/parse_tab.y b/src/powerman/parse_tab.y index eec8057c..3092d977 100644 --- a/src/powerman/parse_tab.y +++ b/src/powerman/parse_tab.y @@ -105,7 +105,7 @@ static Spec current_spec; /* Holds a Spec as it is built */ %} /* script names */ -%token TOK_LOGIN TOK_LOGOUT TOK_STATUS TOK_STATUS_ALL +%token TOK_LOGIN TOK_LOGOUT TOK_STATUS TOK_STATUS_RANGED TOK_STATUS_ALL %token TOK_STATUS_TEMP TOK_STATUS_TEMP_ALL %token TOK_STATUS_BEACON TOK_STATUS_BEACON_ALL %token TOK_BEACON_ON TOK_BEACON_ON_RANGED TOK_BEACON_OFF TOK_BEACON_OFF_RANGED @@ -232,6 +232,8 @@ spec_script : TOK_SCRIPT TOK_LOGIN stmt_block { makeScript(PM_LOG_OUT, (List)$3); } | TOK_SCRIPT TOK_STATUS stmt_block { makeScript(PM_STATUS_PLUGS, (List)$3); +} | TOK_SCRIPT TOK_STATUS_RANGED stmt_block { + makeScript(PM_STATUS_PLUGS_RANGED, (List)$3); } | TOK_SCRIPT TOK_STATUS_ALL stmt_block { makeScript(PM_STATUS_PLUGS_ALL, (List)$3); } | TOK_SCRIPT TOK_STATUS_TEMP stmt_block { diff --git a/src/powerman/pluglist.c b/src/powerman/pluglist.c index 2824e27a..2c607b0a 100644 --- a/src/powerman/pluglist.c +++ b/src/powerman/pluglist.c @@ -50,6 +50,18 @@ static Plug *_create_plug(char *name) return plug; } +static Plug *_copy_plug(Plug *p) +{ + Plug *plug = (Plug *) xmalloc(sizeof(Plug)); + + assert(p != NULL); + + plug->name = p->name ? xstrdup(p->name) : NULL; + plug->node = p->node ? xstrdup(p->node) : NULL; + + return plug; +} + static void _destroy_plug(Plug *plug) { assert(plug != NULL); @@ -82,6 +94,29 @@ PlugList pluglist_create(List plugnames) return pl; } +PlugList pluglist_copy_from_list(List plugs) +{ + PlugList pl = (PlugList) xmalloc(sizeof(struct pluglist)); + + pl->pluglist = list_create((ListDelF)_destroy_plug); + pl->hardwired = false; + + /* create plug from each plug in list */ + if (plugs) { + ListIterator itr; + Plug *p; + + itr = list_iterator_create(plugs); + while ((p = list_next(itr))) { + list_append(pl->pluglist, _copy_plug(p)); + } + list_iterator_destroy(itr); + pl->hardwired = true; + } + + return pl; +} + void pluglist_destroy(PlugList pl) { assert(pl != NULL); diff --git a/src/powerman/pluglist.h b/src/powerman/pluglist.h index 962e11cb..0746b8e9 100644 --- a/src/powerman/pluglist.h +++ b/src/powerman/pluglist.h @@ -33,6 +33,9 @@ typedef enum { EPL_SUCCESS, EPL_DUPNODE, EPL_UNKPLUG, EPL_DUPPLUG, */ PlugList pluglist_create(List plugnames); +/* Create a PlugList, copying plugs from an existing list of plugs */ +PlugList pluglist_copy_from_list(List plugs); + /* Destroy a PlugList and its Plugs */ void pluglist_destroy(PlugList pl);