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 <crosa(a)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