summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hatina <phatina@redhat.com>2012-09-13 09:38:12 +0200
committerPeter Hatina <phatina@redhat.com>2012-09-13 09:39:05 +0200
commit8de6088c8abf4ee1f392b97f63963065335ab977 (patch)
tree5176bc0ba16509811c8bedb3847276ffc4691f22
parentaefe1e49b515b55243096098f820367e53a58493 (diff)
downloadopenlmi-providers-8de6088c8abf4ee1f392b97f63963065335ab977.tar.gz
openlmi-providers-8de6088c8abf4ee1f392b97f63963065335ab977.tar.xz
openlmi-providers-8de6088c8abf4ee1f392b97f63963065335ab977.zip
Introduce CLI tools
-rw-r--r--CMakeLists.txt1
-rw-r--r--cli-tools/CMakeLists.txt34
-rwxr-xr-xcli-tools/cura-power.py74
-rwxr-xr-xcli-tools/cura-service.py92
-rwxr-xr-xcli-tools/cura-user.py79
-rw-r--r--cli-tools/cura/__init__.py0
-rw-r--r--cli-tools/cura/cura_address.py79
-rw-r--r--cli-tools/cura/cura_client_power.py72
-rw-r--r--cli-tools/cura/cura_client_service.py135
-rw-r--r--cli-tools/cura/cura_client_user.py111
-rw-r--r--cli-tools/cura/cura_options.py62
-rw-r--r--cli-tools/setup.py29
12 files changed, 768 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f32881d..58de8a1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,6 +30,7 @@ find_package(KonkretCMPI REQUIRED)
add_subdirectory(src)
add_subdirectory(mof)
+add_subdirectory(cli-tools)
install(PROGRAMS register.sh reg2pegasus.py DESTINATION share/cura-providers)
install(FILES cmake/modules/CuraMacros.cmake DESTINATION share/cmake/Modules)
diff --git a/cli-tools/CMakeLists.txt b/cli-tools/CMakeLists.txt
new file mode 100644
index 0000000..18471b4
--- /dev/null
+++ b/cli-tools/CMakeLists.txt
@@ -0,0 +1,34 @@
+cmake_minimum_required(VERSION 2.6)
+
+set(PYTHON python)
+set(PYTHON_BIN_PATH bin)
+exec_program(
+ ${PYTHON}
+ ARGS "-c \"from distutils.sysconfig import get_python_lib; print(get_python_lib())\""
+ OUTPUT_VARIABLE PYTHON_SITE_PACKAGES_PATH
+)
+
+add_custom_target(
+ PythonInstall ALL
+ COMMAND ${PYTHON} setup.py install
+ --install-lib ${PYTHON_SITE_PACKAGES_PATH}
+ --install-scripts ${PYTHON_BIN_PATH}
+ --root install
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+install(
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/install/bin
+ DESTINATION ${CMAKE_INSTALL_PREFIX}
+ FILES_MATCHING
+ PATTERN "*.py"
+ PERMISSIONS
+ OWNER_READ OWNER_WRITE OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+)
+
+install(
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/install/lib
+ DESTINATION ${CMAKE_INSTALL_PREFIX}
+)
diff --git a/cli-tools/cura-power.py b/cli-tools/cura-power.py
new file mode 100755
index 0000000..4a22d38
--- /dev/null
+++ b/cli-tools/cura-power.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+import sys
+
+from cura.cura_options import CuraBasicOptions
+from cura.cura_address import CuraIpv4Addr, CuraIpv4AddrGenerator
+from cura.cura_client_power import CuraPowerClient
+
+class CuraPowerOptions(CuraBasicOptions):
+ def __init__(self):
+ super(self.__class__, self).__init__(
+ "Available actions:\n"
+ " poweroff, reboot, suspend, hibernate\n"
+ " force-poweroff, force-reboot\n")
+ self.m_parser.set_usage("Usage %prog [options] action")
+
+ @property
+ def good(self):
+ return len(self.m_pos_options) == 1
+
+ @property
+ def action(self):
+ return self.m_pos_options[0] if self.good and self.m_pos_options[0] else ""
+
+if __name__ == "__main__":
+ options = CuraPowerOptions()
+ options.parse(sys.argv)
+ if not options.good:
+ sys.stderr.write(
+ "Wrong tool usage. Run " + __file__ +
+ " --help for detailed help.\n")
+ sys.exit(1)
+
+ client_failed = False
+ client_hostnames = CuraIpv4AddrGenerator(options.hostname).enumerate()
+ client_action = options.action.lower()
+ for client_hostname in client_hostnames:
+ if not len(client_hostname):
+ continue
+ client = CuraPowerClient(client_hostname, options.username, options.password)
+ actions = {
+ "reboot": (client.reboot, "Reboot: "),
+ "poweroff": (client.poweroff, "Poweroff: "),
+ "suspend": (client.suspend, "Suspend: "),
+ "hibernate": (client.hibernate, "Hibernate: ")
+ }
+
+ if not client_action in actions:
+ sys.stdout.write("No such action to perform!\n")
+ sys.exit(1)
+
+ (rval, rparam) = actions[client_action][0]()
+ if rval:
+ sys.stdout.write("%s: %s\n" % (client_hostname,
+ actions[client_action][1] + rparam if rparam else "ok"))
+ else:
+ sys.stderr.write("%s: %s\n" % (client_hostname, rparam))
+ client_failed = True
+
+ sys.exit(client_failed)
diff --git a/cli-tools/cura-service.py b/cli-tools/cura-service.py
new file mode 100755
index 0000000..aab2876
--- /dev/null
+++ b/cli-tools/cura-service.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+import sys
+
+from cura.cura_options import CuraBasicOptions
+from cura.cura_address import CuraIpv4Addr, CuraIpv4AddrGenerator
+from cura.cura_client_service import CuraServiceClient
+
+class CuraServiceOptions(CuraBasicOptions):
+ def __init__(self):
+ super(self.__class__, self).__init__(
+ "Available actions:\n"
+ " start, stop, restart, enable, disable, reload,\n"
+ " try-restart, cond-restart, reload-or-restart,\n"
+ " reload-or-try-restart, status\n")
+ self.m_parser.set_usage("Usage: %prog [options] action service")
+
+ @property
+ def good(self):
+ return len(self.m_pos_options) == 2
+
+ @property
+ def action(self):
+ return self.m_pos_options[0] if self.good and self.m_pos_options[0] else ""
+
+ @property
+ def service(self):
+ if not self.good:
+ return ""
+ return self.m_pos_options[1] if self.good and self.m_pos_options[1] else ""
+
+if __name__ == "__main__":
+ options = CuraServiceOptions()
+ options.parse(sys.argv)
+ if not options.good:
+ sys.stderr.write(
+ "Wrong tool usage. Run " + __file__ +
+ " --help for detailed help.\n")
+ sys.exit(1)
+
+ client_failed = False
+ client_hostnames = CuraIpv4AddrGenerator(options.hostname).enumerate()
+ client_action = options.action.lower()
+ for client_hostname in client_hostnames:
+ if not len(client_hostname):
+ continue
+ client = CuraServiceClient(client_hostname, options.username, options.password)
+ (service, rparam) = client.serviceFind(options.service)
+ if not service:
+ sys.stderr.write("%s: %s\n" % (client_hostname, rparam))
+ continue
+ actions = {
+ "start": (service.start, "Start: "),
+ "stop": (service.stop, "Stop: "),
+ "restart": (service.restart, "Restart: "),
+ "enable": (service.enable, "Enabling: "),
+ "disable": (service.disable, "Disabling: "),
+ "reload": (service.reload, "Reload: "),
+ "try-restart": (service.tryRestart, "Try to restart: "),
+ "cond-restart": (service.condRestart, "Conditional restart: "),
+ "reload-or-restart": (service.reloadRestart, "Reload or restart: "),
+ "reload-or-try-restart": (service.reloadTryRestart, "Reload or try restart: "),
+ "status": (service.status, "Service status: ")
+ }
+
+ if not client_action in actions:
+ sys.stderr.write("No such action to perform!\n")
+ sys.exit(1)
+
+ (rval, rparam) = actions[client_action][0]()
+ if rval:
+ sys.stdout.write("%s: %s\n" % (client_hostname,
+ actions[client_action][1] + rparam if rparam else "ok"))
+ else:
+ sys.stderr.write("%s: %s\n" % (client_hostname, rparam))
+ client_failed = True
+
+ sys.exit(client_failed)
diff --git a/cli-tools/cura-user.py b/cli-tools/cura-user.py
new file mode 100755
index 0000000..98e1964
--- /dev/null
+++ b/cli-tools/cura-user.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+import sys
+
+from cura.cura_options import CuraBasicOptions
+from cura.cura_address import CuraIpv4Addr, CuraIpv4AddrGenerator
+from cura.cura_client_user import CuraUserClient
+
+class CuraUserOptions(CuraBasicOptions):
+ def __init__(self):
+ super(self.__class__, self).__init__(
+ "Available actions:\n"
+ " list-users, list-groups, group-members\n")
+ self.m_parser.set_usage("Usage: %prog [options] action [group]")
+
+ @property
+ def good(self):
+ if not len(self.m_pos_options):
+ return False
+ elif self.m_pos_options[0] == "group-members":
+ return len(self.m_pos_options) == 2
+ return len(self.m_pos_options) == 1
+
+ @property
+ def action(self):
+ return self.m_pos_options[0] if self.good and self.m_pos_options[0] else ""
+
+ @property
+ def group(self):
+ return self.m_pos_options[1] if self.good and self.m_pos_options[1] else ""
+
+if __name__ == "__main__":
+ options = CuraUserOptions()
+ options.parse(sys.argv)
+ if not options.good:
+ sys.stderr.write(
+ "Wrong tool usage. Run " + __file__ +
+ " --help for detailed help.\n")
+ sys.exit(1)
+
+ client_failed = False
+ client_hostnames = CuraIpv4AddrGenerator(options.hostname).enumerate()
+ client_action = options.action.lower()
+ for client_hostname in client_hostnames:
+ if not len(client_hostname):
+ continue
+ client = CuraUserClient(client_hostname, options.username, options.password)
+ actions = {
+ "list-users" : client.listUsers,
+ "list-groups" : client.listGroups
+ }
+
+ if client_action == "group-members":
+ (rval, rparam) = client.listGroupMembers(options.group)
+ elif client_action in actions:
+ (rval, rparam) = actions[client_action]()
+ else:
+ sys.stderr.write("No such action to perform!\n")
+ sys.exit(1)
+
+ if not rval:
+ sys.stderr.write("%s: %s\n" % (client_hostname, rparam))
+ client_failed = True
+
+ sys.exit(client_failed)
diff --git a/cli-tools/cura/__init__.py b/cli-tools/cura/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cli-tools/cura/__init__.py
diff --git a/cli-tools/cura/cura_address.py b/cli-tools/cura/cura_address.py
new file mode 100644
index 0000000..467a1c2
--- /dev/null
+++ b/cli-tools/cura/cura_address.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+import re
+import sys
+import itertools
+
+class CuraIpv4Addr:
+ class CuraIpv4Member:
+ def __init__(self, member):
+ self.m_member = member
+
+ def enumerate(self):
+ pattern = re.compile("^{(.*)}$")
+ match = pattern.search(self.m_member)
+ member = match.group(1) if match else []
+ if not member:
+ return [self.m_member]
+ ranges = (x.split("-") for x in member.split(";"))
+ try:
+ members = []
+ for r in ranges:
+ if not 0 <= int(r[0]) <= 255 or not 0 <= int(r[-1]) <= 255:
+ return []
+ low = int(r[0])
+ high = int(r[-1])
+ if low > high:
+ low, high = high, low
+ members += [str(i) for i in range(low, high + 1)]
+ except ValueError:
+ return []
+ return members
+
+ def __init__(self, addr_pattern):
+ self.m_addr_pattern = addr_pattern
+
+ def enumerate(self):
+ str_members = self.m_addr_pattern.split(".")
+ if len(str_members) != 4:
+ return []
+ members = []
+ for m in str_members:
+ ipm = CuraIpv4Addr.CuraIpv4Member(m)
+ members.append(ipm)
+ addresses = members[3].enumerate()
+ if not addresses:
+ return []
+ for i in reversed(range(0, 3)):
+ combined = []
+ members_to_combine = members[i].enumerate()
+ if not members_to_combine:
+ return []
+ for r in itertools.product(members_to_combine, addresses):
+ combined.append(".".join([r[0], r[1]]))
+ addresses = combined
+ return sorted(set(addresses))
+
+class CuraIpv4AddrGenerator:
+ def __init__(self, addresses):
+ self.m_addresses = addresses
+
+ def enumerate(self):
+ rval = []
+ for addr in self.m_addresses.split(","):
+ rval += CuraIpv4Addr(addr).enumerate()
+ return rval
diff --git a/cli-tools/cura/cura_client_power.py b/cli-tools/cura/cura_client_power.py
new file mode 100644
index 0000000..c2e7b27
--- /dev/null
+++ b/cli-tools/cura/cura_client_power.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+import pywbem
+
+class CuraPowerClient():
+ POWER_CLASS_NAME = "LMI_PowerManagementService"
+ POWER_STATE_SUSPEND = 4
+ POWER_STATE_FORCE_REBOOT = 5
+ POWER_STATE_HIBERNATE = 7
+ POWER_STATE_FORCE_POWEROFF = 8
+ POWER_STATE_POWEROFF = 12
+ POWER_STATE_REBOOT = 15
+
+ def __init__(self, hostname, username="", password=""):
+ self.m_hostname = hostname
+ self.m_username = username
+ self.m_password = password
+ self.m_cliconn = pywbem.WBEMConnection("https://" + self.m_hostname,
+ (self.m_username, self.m_password))
+
+ def __getPowerInstance(self):
+ try:
+ inst_name_list = self.m_cliconn.EnumerateInstanceNames(
+ CuraPowerClient.POWER_CLASS_NAME)
+ except pywbem.cim_operations.CIMError, e:
+ return (None, e.args[1])
+ except pywbem.cim_http.AuthError, e:
+ return (None, e.args[0])
+ inst_list = self.m_cliconn.GetInstance(inst_name_list[0],
+ LocalOnly=False)
+ return (inst_list, "")
+
+ def __powerCallMethod(self, method, **params):
+ (inst, rparam) = self.__getPowerInstance()
+ if not inst:
+ return (False, rparam)
+ try:
+ (rval, rparams) = self.m_cliconn.InvokeMethod(method,
+ inst.path, **params)
+ except pywbem.cim_operations.CIMError, e:
+ return (False, e.args[1])
+ return (rval in (0, 4096), "")
+
+ def poweroff(self):
+ return self.__powerCallMethod("RequestPowerStateChange",
+ PowerState=pywbem.Uint16(CuraPowerClient.POWER_STATE_POWEROFF))
+
+ def reboot(self):
+ return self.__powerCallMethod("RequestPowerStateChange",
+ PowerState=pywbem.Uint16(CuraPowerClient.POWER_STATE_REBOOT))
+
+ def suspend(self):
+ return self.__powerCallMethod("RequestPowerStateChange",
+ PowerState=pywbem.Uint16(CuraPowerClient.POWER_STATE_SUSPEND))
+
+ def hibernate(self):
+ return self.__powerCallMethod("RequestPowerStateChange",
+ PowerState=pywbem.Uint16(CuraPowerClient.POWER_STATE_HIBERNATE))
diff --git a/cli-tools/cura/cura_client_service.py b/cli-tools/cura/cura_client_service.py
new file mode 100644
index 0000000..cf2235e
--- /dev/null
+++ b/cli-tools/cura/cura_client_service.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+import pywbem
+
+class CuraService():
+ def __init__(self, client, inst):
+ self.m_client = client
+ self.m_instance = inst
+
+ def start(self):
+ return self.m_client.serviceStart(self.m_instance)
+
+ def stop(self):
+ return self.m_client.serviceStop(self.m_instance)
+
+ def restart(self):
+ return self.m_client.serviceRestart(self.m_instance)
+
+ def enable(self):
+ return self.m_client.serviceEnable(self.m_instance)
+
+ def disable(self):
+ return self.m_client.serviceDisable(self.m_instance)
+
+ def reload(self):
+ return self.m_client.serviceReload(self.m_instance)
+
+ def tryRestart(self):
+ return self.m_client.serviceTryRestart(self.m_instance)
+
+ def condRestart(self):
+ return self.m_client.serviceCondRestart(self.m_instance)
+
+ def reloadRestart(self):
+ return self.m_client.serviceReloadRestart(self.m_instance)
+
+ def reloadTryRestart(self):
+ return self.m_client.serviceReloadTryRestart(self.m_instance)
+
+ def status(self):
+ return self.m_client.serviceStatus(self.m_instance)
+
+class CuraServiceClient():
+ SERVICE_CLASS_NAME = "LMI_Service"
+
+ def __init__(self, hostname, username = "", password = ""):
+ self.m_hostname = hostname
+ self.m_username = username
+ self.m_password = password
+ self.m_cliconn = pywbem.WBEMConnection("https://" + self.m_hostname,
+ (self.m_username, self.m_password))
+
+ def __serviceGetInstance(self, service):
+ try:
+ inst_name_list = self.m_cliconn.EnumerateInstanceNames(
+ CuraServiceClient.SERVICE_CLASS_NAME)
+ except pywbem.cim_operations.CIMError, e:
+ return (None, e.args[1])
+ except pywbem.cim_http.AuthError, e:
+ return (None, e.args[0])
+ inst_name = filter(lambda n: n["Name"] == service, inst_name_list)
+ if not len(inst_name):
+ return (None, "No such service '" + service + "' found.")
+ inst_list = self.m_cliconn.GetInstance(inst_name[0],
+ LocalOnly = False)
+ return (inst_list, "")
+
+ def __serviceCallMethod(self, service, method):
+ (inst, rparam) = self.__serviceGetInstance(service) if type(service) == str else (service, "")
+ if not inst:
+ return (False, rparam)
+ try:
+ (rval, params) = self.m_cliconn.InvokeMethod(method, inst.path)
+ except pywbem.cim_operations.CIMError, e:
+ return (False, e.args[1] + ": '" + method + "'")
+ return (rval == 0, "")
+
+ def __serviceGetProperty(self, service, prop):
+ (inst, rparam) = self.__serviceGetInstance(service) if type(service) == str else (service, "")
+ if not inst or not prop in inst:
+ return (False, rparam)
+ return (True, inst[prop])
+
+ def serviceFind(self, service):
+ (inst, rparam) = self.__serviceGetInstance(service)
+ if not inst:
+ return (None, rparam)
+ return (CuraService(self, inst), "")
+
+ def serviceStart(self, service):
+ return self.__serviceCallMethod(service, "StartService")
+
+ def serviceStop(self, service):
+ return self.__serviceCallMethod(service, "StopService")
+
+ def serviceRestart(self, service):
+ return self.__serviceCallMethod(service, "RestartService")
+
+ def serviceEnable(self, service):
+ return self.__serviceCallMethod(service, "TurnServiceOn")
+
+ def serviceDisable(self, service):
+ return self.__serviceCallMethod(service, "TurnServiceOff")
+
+ def serviceReload(self, service):
+ return self.__serviceCallMethod(service, "ReloadService")
+
+ def serviceTryRestart(self, service):
+ return self.__serviceCallMethod(service, "TryRestartService")
+
+ def serviceCondRestart(self, service):
+ return self.__serviceCallMethod(service, "CondRestartService")
+
+ def serviceReloadRestart(self, service):
+ return self.__serviceCallMethod(service, "ReloadOrRestartService")
+
+ def serviceReloadTryRestart(self, service):
+ return self.__serviceCallMethod(service, "ReloadOrTryRestartService")
+
+ def serviceStatus(self, service):
+ return self.__serviceGetProperty(service, "Status")
diff --git a/cli-tools/cura/cura_client_user.py b/cli-tools/cura/cura_client_user.py
new file mode 100644
index 0000000..b0b21fc
--- /dev/null
+++ b/cli-tools/cura/cura_client_user.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+import sys
+import pywbem
+
+class CuraUserClient():
+ USER_CLASS_NAME = "LMI_Account"
+ GROUP_CLASS_NAME = "LMI_Group"
+ MEMBER_OF_GROUP_CLASS_NAME = "LMI_MemberOfGroup"
+ ASSIGNED_IDENTITY_CLASS_NAME = "LMI_AssignedAccountIdentity"
+
+ def __init__(self, hostname, username = "", password = ""):
+ self.m_hostname = hostname
+ self.m_username = username
+ self.m_password = password
+ self.m_cliconn = pywbem.WBEMConnection("https://" + self.m_hostname,
+ (self.m_username, self.m_password))
+
+ def __getInstances(self, klass, filter_name = ""):
+ try:
+ inst_name_list = self.m_cliconn.EnumerateInstanceNames(klass)
+ except pywbem.cim_operations.CIMError, e:
+ return (None, e.args[1])
+ except pywbem.cim_http.AuthError, e:
+ return (None, e.args[0])
+ inst_names = inst_name_list
+ if len(filter_name):
+ inst_names = filter(lambda n: n["Name"] == filter_name, inst_name_list)
+ inst_list = []
+ for i in inst_names:
+ inst_list.append(self.m_cliconn.GetInstance(i, LocalOnly = False))
+ if not len(inst_list):
+ return (None, "Not found")
+ return (inst_list, "")
+
+ def __getUserInstances(self):
+ return self.__getInstances(CuraUserClient.USER_CLASS_NAME)
+
+ def __getGroupInstances(self):
+ return self.__getInstances(CuraUserClient.GROUP_CLASS_NAME)
+
+ def __getMemberGroups(self, inst):
+ members = []
+ identities = self.m_cliconn.Associators(inst.path,
+ AssocClass = CuraUserClient.ASSIGNED_IDENTITY_CLASS_NAME)
+ for identity in identities:
+ accounts = self.m_cliconn.Associators(identity.path,
+ AssocClass = CuraUserClient.MEMBER_OF_GROUP_CLASS_NAME)
+ members.extend(accounts)
+ return members
+
+ def __getGroupMembers(self, inst):
+ members = []
+ for g in inst:
+ identities = self.m_cliconn.Associators(g.path,
+ AssocClass = CuraUserClient.MEMBER_OF_GROUP_CLASS_NAME)
+ for i in identities:
+ accounts = self.m_cliconn.Associators(i.path,
+ AssocClass = CuraUserClient.ASSIGNED_IDENTITY_CLASS_NAME)
+ for a in accounts:
+ members.append(a["Name"])
+ return members
+
+ def listUsers(self):
+ (inst_list, rparam) = self.__getUserInstances()
+ if not inst_list:
+ return (False, "No users found")
+ sys.stdout.write("%s:\n" % self.m_hostname)
+ try:
+ for i in inst_list:
+ groups = self.__getMemberGroups(i)
+ gid = groups[0]["InstanceID"].split(":")[-1]
+ sys.stdout.write("%s:x:%s:%s:%s:%s:%s\n" %
+ (i["Name"], i["UserID"], gid, i["ElementName"],
+ i["HomeDirectory"], i["LoginShell"]))
+ except pywbem.cim_operations.CIMError, e:
+ return (False, e.args[1])
+ return (True, "")
+
+ def listGroups(self):
+ (inst_list, rparam) = self.__getGroupInstances()
+ if not inst_list:
+ return (False, "No groups found")
+ for i in inst_list:
+ sys.stdout.write("%s:%s\n" %
+ (i["Name"], i["InstanceID"].split(":")[-1]))
+ return (True, "")
+
+ def listGroupMembers(self, member):
+ (inst_list, rparam) = self.__getInstances(
+ CuraUserClient.GROUP_CLASS_NAME, member)
+ if not inst_list:
+ return (False, "No such group '%s' found" % member)
+ members = self.__getGroupMembers(inst_list)
+ for m in members:
+ sys.stdout.write("%s\n" % m)
+ return (True, "")
diff --git a/cli-tools/cura/cura_options.py b/cli-tools/cura/cura_options.py
new file mode 100644
index 0000000..429740a
--- /dev/null
+++ b/cli-tools/cura/cura_options.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+import sys
+import optparse
+
+class CuraBasicOptions(object):
+ def __init__(self, epil = ""):
+ optparse.OptionParser.format_epilog = lambda self, formatter: self.epilog
+ self.m_parser = optparse.OptionParser(
+ add_help_option = False,
+ epilog = epil)
+ self.m_parser.add_option("", "--help",
+ action="help",
+ help = "print this message")
+ self.m_parser.add_option("-h", "--hostname",
+ action = "store",
+ dest = "hostname",
+ help = "remote machine hostname")
+ self.m_parser.add_option("-u", "--username",
+ action = "store",
+ dest = "username",
+ help = "remote machine username")
+ self.m_parser.add_option("-p", "--password",
+ action = "store",
+ dest = "password",
+ help = "remote machine password")
+
+ def parse(self, argv):
+ (self.m_options, self.m_pos_options) = self.m_parser.parse_args(argv[1:])
+
+ def printHelp(self):
+ self.m_parser.print_help()
+
+ @property
+ def good(self):
+ return len(self.m_pos_options) == 0
+
+ @property
+ def hostname(self):
+ return self.m_options.hostname if self.m_options.hostname else ""
+
+ @property
+ def username(self):
+ return self.m_options.username if self.m_options.username else ""
+
+ @property
+ def password(self):
+ return self.m_options.password if self.m_options.password else ""
diff --git a/cli-tools/setup.py b/cli-tools/setup.py
new file mode 100644
index 0000000..0232b4d
--- /dev/null
+++ b/cli-tools/setup.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# Copyright (C) 2012 Peter Hatina <phatina@redhat.com>
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+from setuptools import setup
+
+setup(
+ name = "cura",
+ version = "0.1",
+ author = "Peter Hatina",
+ author_email = "phatina@redhat.com",
+ description = "CLI tools interfacing cura-providers.",
+ license = "GPLv2",
+ keywords = "cura service user power",
+ packages = ["cura"],
+ scripts = ["cura-service.py", "cura-power.py", "cura-user.py"]
+)