+(* mclu: Mini Cloud
+ * Copyright (C) 2014-2015 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(* Implement 'mclu list'. *)
+
+open Printf
+
+open Utils
+
+module C = Libvirt.Connect
+module D = Libvirt.Domain
+
+let list_what = ref `All
+let set_all () = list_what := `All
+let set_active () = list_what := `ActiveOnly
+let set_templates () = list_what := `TemplatesOnly
+
+let get_arg_speclist () = Arg.align [
+ "--active", Arg.Unit set_active, " List only active/running guests";
+ "--all", Arg.Unit set_all, " List active guests and templates (default)";
+ "--inactive", Arg.Unit set_templates, " List only templates";
+ "--running", Arg.Unit set_active, " List only active/running guests";
+ "--templates", Arg.Unit set_templates, " List only templates";
+]
+
+type dom_info = {
+ dom_name : string;
+ dom_info : D.info;
+}
+
+(* Return the active (running) guests. This utility function is
+ * also called from other places.
+ *)
+let active_guests ?(verbose = false) ?(nodes = Mclu_conf.nodes ()) () =
+ (* A list of running guests, indexed by each node. *)
+ let active_guests =
+ Parallel.map (
+ fun node ->
+ let hostname = node.Mclu_conf.hostname
+ and name = node.Mclu_conf.libvirt_uri in
+ let conn =
+ try Some (C.connect_readonly ~name ())
+ with Libvirt.Virterror msg ->
+ if verbose then
+ eprintf "mclu: %s: %s (ignored)\n" hostname
+ (Libvirt.Virterror.to_string msg);
+ None in
+ let dominfo =
+ match conn with
+ | Some conn ->
+ let dominfos = D.get_domains_and_infos conn [D.ListActive] in
+ (* D.t is abstract so we cannot marshal it. *)
+ List.map (
+ fun (dom, info) ->
+ { dom_name = D.get_name dom; dom_info = info }
+ ) dominfos
+ | None -> [] in
+ (node, dominfo)
+ ) nodes in
+ List.map (fun s -> Marshal.from_bytes s 0) active_guests
+
+let list ~verbose () =
+ let list_what = !list_what in
+
+ (match list_what with
+ | `TemplatesOnly -> ()
+ | `All | `ActiveOnly ->
+ let active_guests = active_guests ~verbose () in
+
+ List.iter (
+ fun ({ Mclu_conf.hostname = hostname }, dominfos) ->
+ List.iter (
+ fun { dom_name = name;
+ dom_info = { D.nr_virt_cpu = vcpus;
+ D.memory = memory_kb;
+ D.state = state } } ->
+ let host_dom_name = sprintf "%s:%s" hostname name in
+ printf "%-28s %s %dvcpus %s\n"
+ host_dom_name (string_of_dom_state state)
+ vcpus (human_size (memory_kb *^ 1024L))
+ ) dominfos
+ ) active_guests
+ );
+
+ (* For quasi-historical reasons, this command also lists the inactive
+ * guests, which in mclu v2 are templates.
+ *)
+ (match list_what with
+ | `ActiveOnly -> ()
+ | `All | `TemplatesOnly ->
+ let templates = Template.template_names () in
+
+ List.iter (
+ fun name ->
+ printf "%-28s template\n" name
+ ) templates
+ )
+
+let run ~verbose = function
+ | [] -> list ~verbose ()
+ | _ ->
+ eprintf "mclu list: Too many arguments\n";
+ exit 1