diff --git a/cloudcontrol/cli/commands/cancel.py b/cloudcontrol/cli/commands/cancel.py
deleted file mode 100644
index c271ca31c0e3dc98d58f6dc65b26e507a7f72d07..0000000000000000000000000000000000000000
--- a/cloudcontrol/cli/commands/cancel.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#coding=utf8
-
-# This file is part of CloudControl.
-#
-# CloudControl is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# CloudControl 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with CloudControl. If not, see .
-
-'''
-CloudControl cancel command
-'''
-
-from cloudcontrol.cli.exception import *
-from sjrpc.core.exceptions import *
-from cloudcontrol.cli.printer import Printer, color
-from cloudcontrol.cli.command import TqlCommand
-
-class Command_cancel(TqlCommand):
- '''Cancel a job'''
-
- def __init__(self, cli, argv0):
- TqlCommand.__init__(self, cli, argv0)
- self.tql_filter += "&r=job&state=running"
-
- def __call__(self, argv):
- # arg parse
- self.parse_args(argv)
- if len(self.args) != 1:
- raise cmdBadArgument()
- # rpc call
- self.rpccall("cancel", self.args[0])
-
- def remote_functions(self):
- return set(("cancel",))
diff --git a/cloudcontrol/cli/commands/kill.py b/cloudcontrol/cli/commands/kill.py
deleted file mode 100644
index 307d0df3ca82b972d9063828becf5cfafd003ace..0000000000000000000000000000000000000000
--- a/cloudcontrol/cli/commands/kill.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#coding=utf8
-
-# This file is part of CloudControl.
-#
-# CloudControl is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# CloudControl 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with CloudControl. If not, see .
-
-'''
-CloudControl Connection related commands
-'''
-
-from cloudcontrol.cli.exception import *
-from sjrpc.core.exceptions import *
-from cloudcontrol.cli.printer import Printer, color
-from cloudcontrol.cli.command import TqlCommand
-
-class Command_kill(TqlCommand):
- '''Kill a server connection'''
-
- def __init__(self, cli, argv0):
- TqlCommand.__init__(self, cli, argv0)
- self.tql_filter += "&con"
-
- def __call__(self, argv):
- # args parse
- self.parse_args(argv)
- if len(self.args) != 1:
- raise cmdBadArgument()
- # rpccall
- self.rpccall("kill", self.args[0])
-
- def remote_functions(self):
- return set(("kill",))
diff --git a/cloudcontrol/cli/commands/purge.py b/cloudcontrol/cli/commands/purge.py
deleted file mode 100644
index d37fc8b57d05bccfed12d9a5df687dfe4192d241..0000000000000000000000000000000000000000
--- a/cloudcontrol/cli/commands/purge.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#coding=utf8
-
-# This file is part of CloudControl.
-#
-# CloudControl is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# CloudControl 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with CloudControl. If not, see .
-
-'''
-CloudControl cancel command
-'''
-
-from cloudcontrol.cli.exception import *
-from sjrpc.core.exceptions import *
-from cloudcontrol.cli.printer import Printer, color
-from cloudcontrol.cli.command import TqlCommand
-
-class Command_purge(TqlCommand):
- '''Purge a job (delete it)'''
-
- def __init__(self, cli, argv0):
- TqlCommand.__init__(self, cli, argv0)
- self.tql_filter += "&r=job&state=done"
-
- def __call__(self, argv):
- # arg parse
- self.parse_args(argv)
- if len(self.args) != 1:
- raise cmdBadArgument()
- # rpc call
- self.rpccall("purge", self.args[0])
-
- def remote_functions(self):
- return set(("purge",))
diff --git a/cloudcontrol/cli/commands/server.py b/cloudcontrol/cli/commands/server.py
index 866d844285eaaa87edb2f677b6d325f890d4d947..5104a1cf7ad4556d8ef9368be8bffecb4ab844ce 100644
--- a/cloudcontrol/cli/commands/server.py
+++ b/cloudcontrol/cli/commands/server.py
@@ -16,12 +16,15 @@
# along with CloudControl. If not, see .
'''
-CloudControl server command
+CloudControl server commands
'''
+
from cloudcontrol.cli.exception import *
from sjrpc.core.exceptions import *
from cloudcontrol.cli.printer import Printer, color
-from cloudcontrol.cli.command import RemoteCommand
+from cloudcontrol.cli.command import RemoteCommand, TqlCommand
+
+import collections
class Command_server(RemoteCommand):
'''Server manipulation command'''
@@ -72,3 +75,168 @@ class Command_server(RemoteCommand):
self.printer.out(self.cli.rpc.call("version"))
except RpcError as e:
raise cmdError("RPCError: %s"%str(e))
+
+
+class Command_kill(TqlCommand):
+ '''Kill a server connection'''
+
+ def __init__(self, cli, argv0):
+ TqlCommand.__init__(self, cli, argv0)
+ self.tql_filter += "&con"
+
+ def __call__(self, argv):
+ # args parse
+ self.parse_args(argv)
+ if len(self.args) != 1:
+ raise cmdBadArgument()
+ # rpccall
+ self.rpccall("kill", self.args[0])
+
+ def remote_functions(self):
+ return set(("kill",))
+
+
+class Command_cancel(TqlCommand):
+ '''Cancel a job'''
+
+ def __init__(self, cli, argv0):
+ TqlCommand.__init__(self, cli, argv0)
+ self.tql_filter += "&r=job&state=running"
+
+ def __call__(self, argv):
+ # arg parse
+ self.parse_args(argv)
+ if len(self.args) != 1:
+ raise cmdBadArgument()
+ # rpc call
+ self.rpccall("cancel", self.args[0])
+
+ def remote_functions(self):
+ return set(("cancel",))
+
+
+class Command_purge(TqlCommand):
+ '''Purge a job (delete it)'''
+
+ def __init__(self, cli, argv0):
+ TqlCommand.__init__(self, cli, argv0)
+ self.tql_filter += "&r=job&state=done"
+
+ def __call__(self, argv):
+ # arg parse
+ self.parse_args(argv)
+ if len(self.args) != 1:
+ raise cmdBadArgument()
+ # rpc call
+ self.rpccall("purge", self.args[0])
+
+ def remote_functions(self):
+ return set(("purge",))
+
+
+class Command_stats(RemoteCommand):
+ """Provide statistics"""
+
+ def __init__(self, cli, argv0):
+ RemoteCommand.__init__(self, cli, argv0)
+ self.set_usage("%prog [options] (hv [tql] | hvpop pop1 [pop2] [...])")
+
+ def __call__(self, argv):
+ self.parse_args(argv)
+ if len(self.args) == 0:
+ raise cmdBadArgument()
+
+ if hasattr(self, "stats_" + self.args[0]):
+ func = getattr(self, "stats_" + self.args[0])
+ func(*self.args[1:])
+ else:
+ raise cmdBadArgument()
+
+ def remote_functions(self):
+ return set(("list",))
+
+ def stats_hvpop(self, *args):
+ if not args:
+ args = ["all"]
+
+ for pop in args:
+ self.printer.out(color["light"] + pop + ": " + color["reset"])
+ self.printer.out(color["light"] + "=" * (len(pop) + 1) + color["reset"])
+ if pop == "all":
+ self.stats_hv()
+ else:
+ self.stats_hv("pop=%s" % pop)
+
+ def stats_hv(self, tql="id", *args):
+ tql = "(%s)&r=hv&con$alloc$cpu$cpualloc$mem$memalloc$sto*$nvm$vmstarted$vmstopped$hmodel" % tql
+ response = self.rpc.call("list", tql)
+
+ count_hv = 0
+ count_hv_allocatable = 0
+ count_vm = 0
+ count_vm_started = 0
+ count_vm_stopped = 0
+ count_cpu_allocated = 0
+ count_cpu_total = 0
+ count_memory_allocated = 0
+ count_memory_total = 0
+ count_disk_allocated = 0
+ count_disk_total = 0
+ count_by_model = collections.defaultdict(lambda: 0)
+
+ # Sum each metric iterating over matching HVs:
+ for hv in response["objects"]:
+ try:
+ count_hv += 1
+ count_hv_allocatable += 1 if hv.get("alloc") == "yes" else 0
+ count_vm += int(hv.get("nvm", 0))
+ count_vm_started += int(hv.get("vmstarted", 0))
+ count_vm_stopped += int(hv.get("vmstopped", 0))
+ count_cpu_allocated += int(hv.get("cpualloc", 0))
+ count_cpu_total += int(hv.get("cpu", 0))
+ count_memory_allocated += int(hv.get("memalloc", 0))
+ count_memory_total += int(hv.get("mem", 0))
+ count_disk_allocated += sum(int(hv.get("sto%s_used" % x, 0)) for x in hv.get("sto", "").split())
+ count_disk_total += sum(int(hv.get("sto%s_size" % x, 0)) for x in hv.get("sto", "").split())
+ count_by_model[hv.get("hmodel", "Unknown")] += 1
+ except ValueError:
+ pass # Ignore errors casting tags as int (most likely a tag timeout error "#ERR")
+
+ # Compute ratios:
+ try:
+ ratio_cpu = float(count_cpu_allocated) / count_cpu_total * 100
+ except ZeroDivisionError:
+ ratio_cpu = 0
+ try:
+ ratio_memory = float(count_memory_allocated) / count_memory_total * 100
+ except ZeroDivisionError:
+ ratio_memory = 0
+ try:
+ ratio_disk = float(count_disk_allocated) / count_disk_total * 100
+ except ZeroDivisionError:
+ ratio_disk = 0
+
+ # Print stats:
+ self._print_stats("Number of hypervisors", "%s (%s are allocatable)",
+ count_hv, count_hv_allocatable)
+ self._print_stats("Number of VM", "%s (%s are started, %s are stopped)",
+ count_vm, count_vm_started, count_vm_stopped)
+ self._print_stats("CPU (threads)", "%s allocated, %s total (%0.1f%% allocated)",
+ count_cpu_allocated, count_cpu_total, ratio_cpu)
+ self._print_stats("Memory", "%sB allocated, %sB total (%0.1f%% allocated)",
+ self.cli.tagdisplay.type_bit(unicode(count_memory_allocated)),
+ self.cli.tagdisplay.type_bit(unicode(count_memory_total)),
+ ratio_memory)
+ self._print_stats("Storage", "%sB allocated, %sB total (%0.1f%% allocated)",
+ self.cli.tagdisplay.type_bit(unicode(count_disk_allocated)),
+ self.cli.tagdisplay.type_bit(unicode(count_disk_total)),
+ ratio_disk)
+ self._print_stats("Hardware", ["%s: %s" % (k, v) for k, v in count_by_model.iteritems()])
+ self.printer.out("") # Empty line
+
+ def _print_stats(self, key, value, *args):
+ if isinstance(value, list):
+ padding = len(key) + 2
+ value = ("\n" + " " * padding).join(value)
+
+ self.printer.out(color["light"] + key + ":" + color["reset"] + " " + value % args)
diff --git a/cloudcontrol/cli/commands/stats.py b/cloudcontrol/cli/commands/stats.py
deleted file mode 100644
index dc620b9fda8335b1581db1cfa49608191da83787..0000000000000000000000000000000000000000
--- a/cloudcontrol/cli/commands/stats.py
+++ /dev/null
@@ -1,134 +0,0 @@
-#coding=utf8
-
-# This file is part of CloudControl.
-#
-# CloudControl is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# CloudControl 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with CloudControl. If not, see .
-
-"""
-CloudControl server command
-"""
-
-from collections import defaultdict
-
-from cloudcontrol.cli.exception import cmdBadArgument
-from cloudcontrol.cli.printer import color
-from cloudcontrol.cli.command import RemoteCommand
-
-
-class Command_stats(RemoteCommand):
- """VM allocation command"""
-
- def __init__(self, cli, argv0):
- RemoteCommand.__init__(self, cli, argv0)
- self.set_usage("%prog [options] (hv [tql] | hvpop pop1 [pop2] [...])")
-
- def __call__(self, argv):
- self.parse_args(argv)
- if len(self.args) == 0:
- raise cmdBadArgument()
-
- if hasattr(self, "stats_" + self.args[0]):
- func = getattr(self, "stats_" + self.args[0])
- func(*self.args[1:])
- else:
- raise cmdBadArgument()
-
- def remote_functions(self):
- return set(("list",))
-
- def stats_hvpop(self, *args):
- if not args:
- args = ["all"]
-
- for pop in args:
- self.printer.out(color["light"] + pop + ": " + color["reset"])
- self.printer.out(color["light"] + "=" * (len(pop) + 1) + color["reset"])
- if pop == "all":
- self.stats_hv()
- else:
- self.stats_hv("pop=%s" % pop)
-
- def stats_hv(self, tql="id", *args):
- tql = "(%s)&r=hv&con$alloc$cpu$cpualloc$mem$memalloc$sto*$nvm$vmstarted$vmstopped$hmodel" % tql
- response = self.rpc.call("list", tql)
-
- count_hv = 0
- count_hv_allocatable = 0
- count_vm = 0
- count_vm_started = 0
- count_vm_stopped = 0
- count_cpu_allocated = 0
- count_cpu_total = 0
- count_memory_allocated = 0
- count_memory_total = 0
- count_disk_allocated = 0
- count_disk_total = 0
- count_by_model = defaultdict(lambda: 0)
-
- # Sum each metric iterating over matching HVs:
- for hv in response["objects"]:
- try:
- count_hv += 1
- count_hv_allocatable += 1 if hv.get("alloc") == "yes" else 0
- count_vm += int(hv.get("nvm", 0))
- count_vm_started += int(hv.get("vmstarted", 0))
- count_vm_stopped += int(hv.get("vmstopped", 0))
- count_cpu_allocated += int(hv.get("cpualloc", 0))
- count_cpu_total += int(hv.get("cpu", 0))
- count_memory_allocated += int(hv.get("memalloc", 0))
- count_memory_total += int(hv.get("mem", 0))
- count_disk_allocated += sum(int(hv.get("sto%s_used" % x, 0)) for x in hv.get("sto", "").split())
- count_disk_total += sum(int(hv.get("sto%s_size" % x, 0)) for x in hv.get("sto", "").split())
- count_by_model[hv.get("hmodel", "Unknown")] += 1
- except ValueError:
- pass # Ignore errors casting tags as int (most likely a tag timeout error "#ERR")
-
- # Compute ratios:
- try:
- ratio_cpu = float(count_cpu_allocated) / count_cpu_total * 100
- except ZeroDivisionError:
- ratio_cpu = 0
- try:
- ratio_memory = float(count_memory_allocated) / count_memory_total * 100
- except ZeroDivisionError:
- ratio_memory = 0
- try:
- ratio_disk = float(count_disk_allocated) / count_disk_total * 100
- except ZeroDivisionError:
- ratio_disk = 0
-
- # Print stats:
- self._print_stats("Number of hypervisors", "%s (%s are allocatable)",
- count_hv, count_hv_allocatable)
- self._print_stats("Number of VM", "%s (%s are started, %s are stopped)",
- count_vm, count_vm_started, count_vm_stopped)
- self._print_stats("CPU (threads)", "%s allocated, %s total (%0.1f%% allocated)",
- count_cpu_allocated, count_cpu_total, ratio_cpu)
- self._print_stats("Memory", "%sB allocated, %sB total (%0.1f%% allocated)",
- self.cli.tagdisplay.type_bit(unicode(count_memory_allocated)),
- self.cli.tagdisplay.type_bit(unicode(count_memory_total)),
- ratio_memory)
- self._print_stats("Storage", "%sB allocated, %sB total (%0.1f%% allocated)",
- self.cli.tagdisplay.type_bit(unicode(count_disk_allocated)),
- self.cli.tagdisplay.type_bit(unicode(count_disk_total)),
- ratio_disk)
- self._print_stats("Hardware", ["%s: %s" % (k, v) for k, v in count_by_model.iteritems()])
- self.printer.out("") # Empty line
-
- def _print_stats(self, key, value, *args):
- if isinstance(value, list):
- padding = len(key) + 2
- value = ("\n" + " " * padding).join(value)
-
- self.printer.out(color["light"] + key + ":" + color["reset"] + " " + value % args)