Autotest (autotest.kernel.org) is beggining to leverage Cobbler to
auto install host systems. It happens to be valuable to our project
to be able to determine the power status of systems, so that we can
better determine if the systems are unresponsive or shut off.

This patch was tested using only APC power switches. Behavior and
command output is expected to be the same on other fencing agents.

The API call return values are probably the big disruption
point comparing it to the other power related calls. I find the
proposal (on this patch) to provide more clear and meaninful
information, but I do acknowledge it's disruptive. Feedback welcome.

Signed-off-by: Cleber Rosa <cr...@redhat.com>
---
 cobbler/action_power.py |   15 ++++++++++++++-
 cobbler/api.py          |    9 +++++++++
 cobbler/cli.py          |    4 ++--
 cobbler/remote.py       |    6 ++++--
 4 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/cobbler/action_power.py b/cobbler/action_power.py
index 8c3083b..dc48da9 100644
--- a/cobbler/action_power.py
+++ b/cobbler/action_power.py
@@ -30,6 +30,7 @@ import os
 import os.path
 import traceback
 import time
+import re
 
 import utils
 import func_utils
@@ -108,8 +109,20 @@ class PowerTool:
         # Try the power command 5 times before giving up.
         # Some power switches are flakey
         for x in range(0,5):
-            rc = utils.subprocess_call(self.logger, cmd, shell=False)
+            output, rc = utils.subprocess_sp(self.logger, cmd, shell=False)
             if rc == 0:
+                # If the desired state is actually a query for the status
+                # return different information than command return code
+                if desired_state == 'status':
+                    match = re.match('(^Status:\s)(ON|OFF)', output)
+                    if match:
+                        power_status = match.groups()[1]
+                        if power_status == 'ON':
+                            return True
+                        else:
+                            return False
+                    utils.die(self.logger,"command succeeded (rc=%s), but 
output ('%s') was not understood" % (rc, output))
+                    return None
                 break
             else:
                 time.sleep(2)
diff --git a/cobbler/api.py b/cobbler/api.py
index cb94995..3a1c5a4 100644
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -921,6 +921,15 @@ class BootAPI:
         time.sleep(5)
         return self.power_on(system, user, password, logger=logger)
 
+    def power_status(self, system, user=None, password=None, logger=None):
+        """
+        Returns the power status for a system that has power management 
configured.
+
+        @return: 0  the system is powered on, False if it's not or None on 
error
+        """
+        return action_power.PowerTool(self._config, system, self, user, 
password, logger = logger).power("status")
+
+
     # 
==========================================================================
 
     def clear_logs(self, system, logger=None):
diff --git a/cobbler/cli.py b/cobbler/cli.py
index 3b3efa7..99da153 100755
--- a/cobbler/cli.py
+++ b/cobbler/cli.py
@@ -42,7 +42,7 @@ import item_file
 OBJECT_ACTIONS   = {
    "distro"    : "add copy edit find list remove rename report".split(" "),
    "profile"   : "add copy dumpvars edit find getks list remove rename 
report".split(" "),
-   "system"    : "add copy dumpvars edit find getks list remove rename report 
poweron poweroff reboot".split(" "),
+   "system"    : "add copy dumpvars edit find getks list remove rename report 
poweron poweroff powerstatus reboot".split(" "),
    "image"     : "add copy edit find list remove rename report".split(" "),
    "repo"      : "add copy edit find list remove rename report".split(" "),
    "mgmtclass" : "add copy edit find list remove rename report".split(" "),
@@ -295,7 +295,7 @@ class BootCLI:
             keys.sort()
             for x in keys:
                print "%s : %s" % (x, data[x])
-        elif object_action in [ "poweron", "poweroff", "reboot" ]:
+        elif object_action in [ "poweron", "poweroff", "powerstatus", "reboot" 
]:
             power={}
             power["power"] = object_action.replace("power","")
             power["systems"] = [options.name]
diff --git a/cobbler/remote.py b/cobbler/remote.py
index f88451e..88523e1 100644
--- a/cobbler/remote.py
+++ b/cobbler/remote.py
@@ -1862,7 +1862,7 @@ class CobblerXMLRPCInterface:
         """
         Internal implementation used by background_power, do not call
         directly if possible.  
-        Allows poweron/poweroff/reboot of a system specified by object_id.
+        Allows poweron/poweroff/powerstatus/reboot of a system specified by 
object_id.
         """
         obj = self.__get_object(object_id)
         self.check_access(token, "power_system", obj)
@@ -1870,10 +1870,12 @@ class CobblerXMLRPCInterface:
             rc=self.api.power_on(obj, user=None, password=None, logger=logger)
         elif power=="off":
             rc=self.api.power_off(obj, user=None, password=None, logger=logger)
+        elif power=="status":
+            rc=self.api.power_status(obj, user=None, password=None, 
logger=logger)
         elif power=="reboot":
             rc=self.api.reboot(obj, user=None, password=None, logger=logger)
         else:
-            utils.die(self.logger, "invalid power mode '%s', expected 
on/off/reboot" % power)
+            utils.die(self.logger, "invalid power mode '%s', expected 
on/off/status/reboot" % power)
         return rc
 
     def get_config_data(self,hostname):
-- 
1.7.1

_______________________________________________
cobbler-devel mailing list
cobbler-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/cobbler-devel

Reply via email to