Tested against commit b2aaf2b3f5c8d758825028dacdeadbdd2e50e4a8, with my
earlier reporting fixes patch
(0001-Fixed-issues-when-reporting-on-a-set-of-fields-that.patch
<
https://fedorahosted.org/pipermail/cobbler-devel/attachments/20090406/c0c...>)
already applied. Please commit this patch AFTER committing the previous
patch.
So, now one can issue XMLRPC calls to retrieve reports from remote
cobbler servers.
E.g. client usage:
---
import xmlrpclib
remote =
xmlrpclib.ServerProxy("http://<remote_cobbler_server>/cobbler_api",
allow_none=True)
# get a 'cobbler report --what=systems' report (no headers)
report1 = remote.report(True, 'systems', None, 'text', 'all',
None)
# get a 'cobbler report --name=hp_003 --format=mediawiki' report (no
headers)
report2 = remote.report(True, None, 'hp_003', 'mediawiki', None)
# get a 'cobbler report --what=distros --format=csv
--fields='name,ks_meta[tree]' report (with headers)
report3 = remote.report(True, 'distros', None, 'csv',
'name,ks_meta[tree]', False)
---
The 'function prototype' for the remote function (from remote.py) is the
following:
###
def
report(self,api=True,what=None,name=None,type=None,fields=None,noheaders=None,**rest):
###
I haven't figured out how to get xmlrpclib to recognize the positional
parameters -- hence the odd client examples (all args are listed and are
listed in order). Perhaps one of you might be able to figure this out,
since it's annoying to have to remember the prototype every time you
want to invoke an XMLRPC reporting call.
Cheers,
- A.
From 888b569e91009dcb6212e4164ab437144733a9cc Mon Sep 17 00:00:00 2001
From: Adam Rosenwald <thestrider(a)gmail.com>
Date: Tue, 7 Apr 2009 03:23:09 -0400
Subject: [PATCH] Enabled XMLRPC reporting function.
ARos
---
cobbler/action_report.py | 91 +++++++++++++++++++++++-----------------------
cobbler/api.py | 4 +-
cobbler/remote.py | 6 +++
3 files changed, 54 insertions(+), 47 deletions(-)
diff --git a/cobbler/action_report.py b/cobbler/action_report.py
index 9f4367e..8d27ccf 100644
--- a/cobbler/action_report.py
+++ b/cobbler/action_report.py
@@ -214,20 +214,18 @@ class Report:
return opentable + outputheaders + outputbody + closetable
- def print_formatted_data(self, data, order, report_type, noheaders):
+ def get_formatted_data(self, data, order, report_type, noheaders):
"""
Used for picking the correct format to output data as
"""
if report_type == "csv":
- print self.reporting_csv(data, order, noheaders)
+ return self.reporting_csv(data, order, noheaders)
if report_type == "mediawiki":
- print self.reporting_mediawiki(data, order, noheaders)
+ return self.reporting_mediawiki(data, order, noheaders)
if report_type == "trac":
- print self.reporting_trac(data, order, noheaders)
+ return self.reporting_trac(data, order, noheaders)
if report_type == "doku":
- print self.reporting_doku(data, order, noheaders)
-
- return True
+ return self.reporting_doku(data, order, noheaders)
def reporting_sorter(self, a, b):
"""
@@ -235,26 +233,28 @@ class Report:
"""
return cmp(a.name, b.name)
- def reporting_print_sorted(self, collection):
+ def reporting_get_sorted(self, collection):
"""
Prints all objects in a collection sorted by name
"""
collection = [x for x in collection]
collection.sort(self.reporting_sorter)
+ str = ""
for x in collection:
- print x.printable()
- return True
+ str += x.printable() + "\n"
+ return str
def reporting_list_names2(self, collection, name):
"""
Prints a specific object in a collection.
"""
obj = collection.find(name=name)
+ str = ""
if obj is not None:
- print obj.printable()
- return True
+ str += obj.printable() + "\n"
+ return str
- def reporting_print_all_fields(self, collection, report_name, report_type,
report_noheaders):
+ def reporting_get_all_fields(self, collection, report_name, report_type,
report_noheaders):
"""
Prints all fields in a collection as a table given the report type
"""
@@ -264,7 +264,7 @@ class Report:
if collection:
collection = [collection]
else:
- return
+ raise CX(_("%s is not a valid item." % report_name))
collection = [x for x in collection]
collection.sort(self.reporting_sorter)
@@ -282,12 +282,12 @@ class Report:
for (device, info) in value.iteritems():
for (info_header, info_value) in info.iteritems():
item[info_header] = str(device) + ': ' +
str(info_value)
- # needs to create order list for print_formatted_fields
+ # needs to create order list for get_formatted_fields
if count == 0:
out_order.append(info_header)
else:
item[key] = value
- # needs to create order list for print_formatted_fields
+ # needs to create order list for get_formatted_fields
if count == 0:
out_order.append(key)
@@ -295,11 +295,9 @@ class Report:
data.append(item)
- self.print_formatted_data(data = data, order = out_order, report_type =
report_type, noheaders = report_noheaders)
-
- return True
+ return self.get_formatted_data(data = data, order = out_order, report_type =
report_type, noheaders = report_noheaders)
- def reporting_print_x_fields(self, collection, report_name, report_type,
report_fields, report_noheaders):
+ def reporting_get_x_fields(self, collection, report_name, report_type, report_fields,
report_noheaders):
"""
Prints specific fields in a collection as a table given the report type
"""
@@ -309,7 +307,7 @@ class Report:
if collection:
collection = [collection]
else:
- return
+ raise CX(_("%s is not a valid item." % report_name))
collection = [x for x in collection]
collection.sort(self.reporting_sorter)
@@ -321,13 +319,11 @@ class Report:
item = self.fielder(structure, fields_list)
data.append(item)
- self.print_formatted_data(data = data, order = fields_list, report_type =
report_type, noheaders = report_noheaders)
-
- return True
+ return self.get_formatted_data(data = data, order = fields_list, report_type =
report_type, noheaders = report_noheaders)
# -------------------------------------------------------
- def run(self, report_what = None, report_name = None, report_type = None,
report_fields = None, report_noheaders = None):
+ def run(self, api = False, report_what = None, report_name = None, report_type =
None, report_fields = None, report_noheaders = None):
"""
Get remote profiles and distros and sync them locally
"""
@@ -338,38 +334,39 @@ class Report:
3. Handles specific fields of report outputs as table given a format
"""
+ str = ""
if report_type == 'text' and report_fields == 'all':
if report_what in [ "all", "distros", "distro"
]:
if report_name:
- self.reporting_list_names2(self.api.distros(), report_name)
+ str += self.reporting_list_names2(self.api.distros(), report_name)
else:
- self.reporting_print_sorted(self.api.distros())
+ str += self.reporting_get_sorted(self.api.distros())
if report_what in [ "all", "profiles",
"profile" ]:
if report_name:
- self.reporting_list_names2(self.api.profiles(), report_name)
+ str += self.reporting_list_names2(self.api.profiles(), report_name)
else:
- self.reporting_print_sorted(self.api.profiles())
+ str += self.reporting_get_sorted(self.api.profiles())
if report_what in [ "all", "systems", "system"
]:
if report_name:
- self.reporting_list_names2(self.api.systems(), report_name)
+ str += self.reporting_list_names2(self.api.systems(), report_name)
else:
- self.reporting_print_sorted(self.api.systems())
+ str += self.reporting_get_sorted(self.api.systems())
if report_what in [ "all", "repos", "repo" ]:
if report_name is not None:
- self.reporting_list_names2(self.api.repos(), report_name)
+ str += self.reporting_list_names2(self.api.repos(), report_name)
else:
- self.reporting_print_sorted(self.api.repos())
+ str += self.reporting_get_sorted(self.api.repos())
if report_what in [ "all", "images", "image"
]:
if report_name is not None:
- self.reporting_list_names2(self.api.images(), report_name)
+ str += self.reporting_list_names2(self.api.images(), report_name)
else:
- self.reporting_print_sorted(self.api.images())
+ str += self.reporting_get_sorted(self.api.images())
elif report_type == 'text' and report_fields != 'all':
raise CX(_("The 'text' type can only be used with field set to
'all'"))
@@ -377,33 +374,37 @@ class Report:
elif report_type != 'text' and report_fields == 'all':
if report_what in [ "all", "distros", "distro"
]:
- self.reporting_print_all_fields(self.api.distros(), report_name,
report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.distros(), report_name,
report_type, report_noheaders)
if report_what in [ "all", "profiles",
"profile" ]:
- self.reporting_print_all_fields(self.api.profiles(), report_name,
report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.profiles(), report_name,
report_type, report_noheaders)
if report_what in [ "all", "systems", "system"
]:
- self.reporting_print_all_fields(self.api.systems(), report_name,
report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.systems(), report_name,
report_type, report_noheaders)
if report_what in [ "all", "repos", "repo" ]:
- self.reporting_print_all_fields(self.api.repos(), report_name,
report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.repos(), report_name,
report_type, report_noheaders)
if report_what in [ "all", "images", "image"
]:
- self.reporting_print_all_fields(self.api.images(), report_name,
report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.images(), report_name,
report_type, report_noheaders)
else:
if report_what in [ "all", "distros", "distro"
]:
- self.reporting_print_x_fields(self.api.distros(), report_name,
report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.distros(), report_name,
report_type, report_fields, report_noheaders)
if report_what in [ "all", "profiles",
"profile" ]:
- self.reporting_print_x_fields(self.api.profiles(), report_name,
report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.profiles(), report_name,
report_type, report_fields, report_noheaders)
if report_what in [ "all", "systems", "system"
]:
- self.reporting_print_x_fields(self.api.systems(), report_name,
report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.systems(), report_name,
report_type, report_fields, report_noheaders)
if report_what in [ "all", "repos", "repo" ]:
- self.reporting_print_x_fields(self.api.repos(), report_name, report_type,
report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.repos(), report_name,
report_type, report_fields, report_noheaders)
if report_what in [ "all", "images", "image"
]:
- self.reporting_print_x_fields(self.api.images(), report_name,
report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.images(), report_name,
report_type, report_fields, report_noheaders)
+ if api:
+ return str
+ else:
+ print str
diff --git a/cobbler/api.py b/cobbler/api.py
index a4b44c5..ee4d652 100644
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -702,12 +702,12 @@ class BootAPI:
include_systems = systems
)
- def report(self, report_what = None, report_name = None, report_type = None,
report_fields = None, report_noheaders = None):
+ def report(self, api=False, report_what = None, report_name = None, report_type =
None, report_fields = None, report_noheaders = None):
"""
Report functionality for cobbler
"""
reporter = action_report.Report(self._config)
- return reporter.run(report_what = report_what, report_name = report_name,\
+ return reporter.run(api = api, report_what = report_what, report_name =
report_name,\
report_type = report_type, report_fields = report_fields,\
report_noheaders = report_noheaders)
diff --git a/cobbler/remote.py b/cobbler/remote.py
index 43e9c0a..2f81ad9 100644
--- a/cobbler/remote.py
+++ b/cobbler/remote.py
@@ -553,6 +553,12 @@ class CobblerXMLRPCInterface:
self._log("version",token=token)
return self.api.version(extended=True)
+ def
report(self,api=True,what=None,name=None,type=None,fields=None,noheaders=None,**rest):
+ """
+ Returns a cobbler report as a string
+ """
+ return self.api.report(api,what,name,type,fields,noheaders)
+
def get_distros(self,page=None,results_per_page=None,token=None,**rest):
"""
Returns all cobbler distros as an array of hashes.
--
1.5.5.1