2 * Copyright (C) 2014-2015 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 (* Implement 'mclu on' and 'mclu off'. *)
25 let get_arg_speclist () = Arg.align [
28 let wake ~verbose nodes =
30 match Config.path_wol with
33 eprintf "mclu: Wake-on-LAN is not available
34 Recompile mclu with the 'wol' program installed\n";
37 (* Only wake nodes which are switched off. *)
38 let nodes = List.filter (fun { Mclu_status.node_on = on } -> not on) nodes in
39 let nodes = List.map (fun { Mclu_status.node = node } -> node) nodes in
43 | { Mclu_conf.mac_addr = Some mac_addr } ->
44 let cmd = sprintf "%s %s" (quote wol) (quote mac_addr) in
45 if verbose then printf "%s\n%!" cmd;
46 if Sys.command cmd <> 0 then (
47 eprintf "mclu: wol: command failed\n";
50 | { Mclu_conf.hostname = hostname; mac_addr = None } ->
51 eprintf "mclu: Wake-on-LAN is not configured for node %s
52 Edit mclu.conf and add 'mac=<MAC address>' to this host line.\n" hostname;
56 let shutdown ~verbose nodes =
57 (* Only shutdown nodes which are switched on. *)
58 let nodes = List.filter (fun { Mclu_status.node_on = on } -> on) nodes in
59 let nodes = List.map (fun { Mclu_status.node = node } -> node) nodes in
61 (* Get the active guests on these nodes. *)
62 let active_guests = Mclu_list.active_guests ~verbose ~nodes () in
67 fun ({ Mclu_conf.hostname = hostname } as node) ->
68 let guests = try List.assoc node active_guests with Not_found -> [] in
69 if guests <> [] then (
70 eprintf "mclu: node %s has %d guest(s) running: %s
71 Shut down these guests before turning off the node.\n"
72 hostname (List.length guests)
74 (List.map (fun guest -> guest.Mclu_list.dom_name) guests));
78 (* We have to be cunning about this else ssh will return an error. *)
80 sprintf "ssh -o ForwardX11=no root@%s '(sleep 5; poweroff) </dev/null >/dev/null 2>&1 &'"
82 if verbose then printf "%s\n%!" cmd;
83 if Sys.command cmd <> 0 then (
84 eprintf "mclu: %s: poweroff: command failed\n" hostname;
93 let expand_wildcards exprs =
94 let regexps = List.map regexp_of_glob exprs in
95 let regexps = List.map Pcre.regexp regexps in
97 let nodes = Mclu_status.node_statuses () in
101 fun { Mclu_status.node = { Mclu_conf.hostname = hostname } } ->
102 List.exists (fun rex -> Pcre.pmatch ~rex hostname) regexps
105 if List.length nodes < List.length exprs then (
106 eprintf "mclu: [on|off]: some wildcards don't match hostnames\n";
112 let run ~verbose ~on = function
114 let nodes = expand_wildcards xs in
115 (if on then wake else shutdown) ~verbose nodes
117 eprintf "Usage: mclu [on|off] node|wildcard ...\n";