summaryrefslogtreecommitdiffstats
path: root/cobbler
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-09-12 16:02:54 -0400
committerMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-09-12 16:02:54 -0400
commit1d215c67c7404d37ca833acdcfe75b1bd515b592 (patch)
treed9483f546a650a9f696b41a3696a88af2bd0dbe0 /cobbler
parent27e40ba1ab0412e7d47a8858193120d766841587 (diff)
downloadthird_party-cobbler-1d215c67c7404d37ca833acdcfe75b1bd515b592.tar.gz
third_party-cobbler-1d215c67c7404d37ca833acdcfe75b1bd515b592.tar.xz
third_party-cobbler-1d215c67c7404d37ca833acdcfe75b1bd515b592.zip
Adding additional exception handling and logging to WebUI.
Diffstat (limited to 'cobbler')
-rw-r--r--cobbler/remote.py25
-rw-r--r--cobbler/utils.py20
-rw-r--r--cobbler/webui/CobblerWeb.py137
3 files changed, 121 insertions, 61 deletions
diff --git a/cobbler/remote.py b/cobbler/remote.py
index cca0df9..2673cb9 100644
--- a/cobbler/remote.py
+++ b/cobbler/remote.py
@@ -146,7 +146,7 @@ class CobblerXMLRPCInterface:
"""
return self.__get_all(self.api.repos())
- def __get_specific(self,collection,name):
+ def __get_specific(self,collection,name,flatten=False):
"""
Internal function to return a hash representation of a given object if it exists,
otherwise an empty hash will be returned.
@@ -155,31 +155,34 @@ class CobblerXMLRPCInterface:
item = collection.find(name=name)
if item is None:
return self._fix_none({})
- return self._fix_none(item.to_datastruct())
+ result = item.to_datastruct()
+ if flatten:
+ result = utils.flatten(result)
+ return self._fix_none(result)
- def get_distro(self,name,token=None):
+ def get_distro(self,name,flatten=False,token=None):
"""
Returns the distro named "name" as a hash.
"""
- return self.__get_specific(self.api.distros(),name)
+ return self.__get_specific(self.api.distros(),name,flatten=flatten)
- def get_profile(self,name,token=None):
+ def get_profile(self,name,flatten=False,token=None):
"""
Returns the profile named "name" as a hash.
"""
- return self.__get_specific(self.api.profiles(),name)
+ return self.__get_specific(self.api.profiles(),name,flatten=flatten)
- def get_system(self,name,token=None):
+ def get_system(self,name,flatten=False,token=None):
"""
Returns the system named "name" as a hash.
"""
- return self.__get_specific(self.api.systems(),name)
+ return self.__get_specific(self.api.systems(),name,flatten=flatten)
- def get_repo(self,name,token=None):
+ def get_repo(self,name,flatten=False,token=None):
"""
Returns the repo named "name" as a hash.
"""
- return self.__get_specific(self.api.repos(),name)
+ return self.__get_specific(self.api.repos(),name,flatten=flatten)
def get_distro_as_rendered(self,name,token=None):
"""
@@ -748,6 +751,8 @@ if __name__ == "__main__":
print remote.get_systems()
print remote.get_repos()
+ print remote.get_system("AA:BB:AA:BB:AA:BB",True) # flattened
+
# now simulate hitting a "sync" button in a WebUI
print remote.sync(token)
diff --git a/cobbler/utils.py b/cobbler/utils.py
index 23dcca6..6a7618d 100644
--- a/cobbler/utils.py
+++ b/cobbler/utils.py
@@ -22,6 +22,7 @@ import shutil
import string
import traceback
import logging
+from cexceptions import *
from rhpl.translate import _, N_, textdomain, utf8
import api # factor out
@@ -231,7 +232,9 @@ def input_string_or_hash(options,delim=","):
"""
if options is None:
return (True, {})
- elif type(options) != dict:
+ elif type(options) == list:
+ raise CX(_("No idea what to do with list: %s") % options)
+ elif type(options) == str:
new_dict = {}
tokens = options.split(delim)
for t in tokens:
@@ -244,9 +247,11 @@ def input_string_or_hash(options,delim=","):
return (False, {})
new_dict.pop('', None)
return (True, new_dict)
- else:
+ elif type(options) == dict:
options.pop('',None)
return (True, options)
+ else:
+ raise CX(_("Foreign options type"))
def grab_tree(obj):
"""
@@ -288,11 +293,18 @@ def blender(remove_hashes, root_obj):
# sanitize output for koan and kernel option lines, etc
if remove_hashes:
- results["kernel_options"] = hash_to_string(results["kernel_options"])
- results["ks_meta"] = hash_to_string(results["ks_meta"])
+ results = flatten(results)
return results
+def flatten(data):
+ # convert certain nested hashes to strings.
+ if data.has_key("kernel_options"):
+ data["kernel_options"] = hash_to_string(data["kernel_options"])
+ if data.has_key("ks_meta"):
+ data["ks_meta"] = hash_to_string(data["ks_meta"])
+ return data
+
def __consolidate(node,results):
"""
Merge data from a given node with the aggregate of all
diff --git a/cobbler/webui/CobblerWeb.py b/cobbler/webui/CobblerWeb.py
index 02fcde8..236ebcf 100644
--- a/cobbler/webui/CobblerWeb.py
+++ b/cobbler/webui/CobblerWeb.py
@@ -13,7 +13,27 @@ import exceptions
import xmlrpclib
from Cheetah.Template import Template
import os
+import traceback
+import string
from cobbler.utils import *
+import logging
+import sys
+
+logger = logging.getLogger("cobbler.webui")
+logger.setLevel(logging.DEBUG)
+ch = logging.FileHandler("/var/log/cobbler/webui.log")
+ch.setLevel(logging.DEBUG)
+formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
+ch.setFormatter(formatter)
+logger.addHandler(ch)
+
+def log_exc():
+ (t, v, tb) = sys.exc_info()
+ logger.info("Exception occured: %s" % t )
+ logger.info("Exception value: %s" % v)
+ logger.info("Exception Info:\n%s" % string.join(traceback.format_list(traceback.extract_tb(tb))))
+
+
class CobblerWeb(object):
"""
@@ -34,7 +54,7 @@ class CobblerWeb(object):
self.username = username
self.password = password
- def __xmlrpc(self):
+ def __xmlrpc_setup(self):
"""
Sets up the connection to the Cobbler XMLRPC server. Right now, the
r/w server is required. In the future, it may be possible to instantiate
@@ -51,11 +71,16 @@ class CobblerWeb(object):
Call the templating engine (Cheetah), wrapping up the location
of files while we're at it.
"""
- data['base_url'] = self.base_url
- #filepath = "%s/%s" % (os.path.dirname(__file__), template)
- filepath = os.path.join("/usr/share/cobbler/webui_templates/",template)
- tmpl = Template( file=filepath, searchList=data )
- return str(tmpl)
+ try:
+ data['base_url'] = self.base_url
+ #filepath = "%s/%s" % (os.path.dirname(__file__), template)
+ filepath = os.path.join("/usr/share/cobbler/webui_templates/",template)
+ tmpl = Template( file=filepath, searchList=data )
+ return str(tmpl)
+ except:
+ logger.error("An error has occurred.") # FIXME: remove
+ log_exc()
+ return self.error_page("Error while rendering page. See /var/log/cobbler/webui.log")
def modes(self):
"""
@@ -80,8 +105,9 @@ class CobblerWeb(object):
# Settings
# ------------------------------------------------------------------------ #
def settings_view(self):
+ self.__xmlrpc_setup()
return self.__render( 'item.tmpl', {
- 'item_data': self.__xmlrpc().get_settings(),
+ 'item_data': self.remote.get_settings(),
'caption': "Cobbler Settings"
} )
@@ -89,16 +115,16 @@ class CobblerWeb(object):
# Distributions
# ------------------------------------------------------------------------ #
def distro_view(self, distribution):
- # get_distro_for_koan() flattens out the inherited options
- #distro = self.__xmlrpc().get_distro_for_koan(distribution)
+ self.__xmlrpc_setup()
return self.__render( 'item.tmpl', {
- 'item_data': self.__xmlrpc().get_distro(distribution),
+ 'item_data': self.remote.get_distro(distribution,True),
'caption': "Distribution \"%s\" Details" % distribution
} )
def distro_list(self):
+ self.__xmlrpc_setup()
return self.__render( 'distro_list.tmpl', {
- 'distros': self.__xmlrpc().get_distros()
+ 'distros': self.remote.get_distros()
} )
# ------------------------------------------------------------------------ #
@@ -107,83 +133,99 @@ class CobblerWeb(object):
# if the system list is huge, this will probably need to use an
# iterator so the list doesn't get copied around
def system_list(self):
+ self.__xmlrpc_setup()
return self.__render( 'system_list.tmpl', {
- 'systems': self.__xmlrpc().get_systems()
+ 'systems': self.remote.get_systems()
} )
def system_add(self):
+ self.__xmlrpc_setup()
return self.__render( 'system_edit.tmpl', {
'system': None,
- 'profiles': self.__xmlrpc().get_profiles()
+ 'profiles': self.remote.get_profiles()
} )
def system_view(self, name):
+ self.__xmlrpc_setup()
return self.__render( 'item.tmpl', {
- 'item_data': self.__xmlrpc().get_system(name),
+ 'item_data': self.remote.get_system(name,True),
'caption': "Profile %s Settings" % name
} )
- def system_save(self, name=None, profile=None, new_or_edit=None, mac=None, ip=None, hostname=None, kopts=None, ksmeta=None, netboot='n', **args):
+ def system_save(self, name=None, profile=None, new_or_edit=None, mac=None, ip=None, hostname=None, kopts=None, ksmeta=None, netboot='n', dhcp_tag=None, **args):
+ self.__xmlrpc_setup()
+
# parameter checking
if name is None:
return self.error_page("System name parameter is REQUIRED.")
-
- if mac is None and ip is None and hostname is None:
+ if mac is None and ip is None and hostname is None and not is_mac(name):
return self.error_page("System must have at least one of MAC/IP/hostname.")
-
- # resolve_ip, is_mac, and is_ip are from cobbler.utils
if hostname and not ip:
ip = resolve_ip( hostname )
-
if mac and not is_mac( mac ):
return self.error_page("The provided MAC address appears to be invalid.")
-
if ip and not is_ip( ip ):
return self.error_page("The provided IP address appears to be invalid.")
- # set up XMLRPC - token is in self.token
- self.__xmlrpc()
-
+ # grab a reference to the object
if new_or_edit == "edit":
- system = self.remote.get_system_handle( name, self.token )
+ try:
+ system = self.remote.get_system_handle( name, self.token )
+ except:
+ return self.error_page("Failed to lookup system: %s" % name)
else:
system = self.remote.new_system( self.token )
- self.remote.modify_system( system, 'name', name, self.token )
-
- if profile:
- self.remote.modify_system(system, 'profile', profile, self.token)
- if mac:
- self.remote.modify_system(system, 'mac', mac, self.token)
- if ip:
- self.remote.modify_system(system, 'ip', ip, self.token)
- if hostname:
- self.remote.modify_system(system, 'hostname', hostname, self.token)
- if kopts:
- self.remote.modify_system(system, 'kopts', kopts, self.token)
- if ksmeta:
- self.remote.modify_system(system, 'ksmeta', ksmeta, self.token)
-
- self.remote.save_system( system, self.token )
+ # go!
+ try:
+ self.remote.modify_system(system, 'name', name, self.token )
+ self.remote.modify_system(system, 'profile', profile, self.token)
+ if mac:
+ self.remote.modify_system(system, 'mac', mac, self.token)
+ if ip:
+ self.remote.modify_system(system, 'ip', ip, self.token)
+ if hostname:
+ self.remote.modify_system(system, 'hostname', hostname, self.token)
+ if kopts:
+ self.remote.modify_system(system, 'kopts', kopts, self.token)
+ if ksmeta:
+ self.remote.modify_system(system, 'ksmeta', ksmeta, self.token)
+ if netboot:
+ self.remote.modify_system(system, 'netboot-enabled', netboot, self.token)
+ if dhcp_tag:
+ self.remote.modify_system(system, 'dhcp-tag', dhcp_tag, self.token)
+ self.remote.save_system( system, self.token)
+ except Exception, e:
+ # FIXME: get the exact error message and display to the user.
+ log_exc()
+ return self.error_page("Error while saving system: %s" % str(e))
return self.system_view( name=name )
+
+ #def tb2str(self,tb):
+ # print " ".join(traceback.format_list(traceback.extract_tb(tb)))
+ # return ""
+
def system_edit(self, name):
+ self.__xmlrpc_setup()
return self.__render( 'system_edit.tmpl', {
- 'system': self.__xmlrpc().get_system(name),
- 'profiles': self.__xmlrpc().get_profiles()
+ 'system': self.remote.get_system(name,True),
+ 'profiles': self.remote.get_profiles()
} )
# ------------------------------------------------------------------------ #
# Profiles
# ------------------------------------------------------------------------ #
def profile_list(self):
+ self.__xmlrpc_setup()
return self.__render( 'profile_list.tmpl', {
- 'profiles': self.__xmlrpc().get_profiles()
+ 'profiles': self.remote.get_profiles()
} )
def profile_add(self):
+ self.__xmlrpc_setup()
return self.__render( 'profile_add.tmpl', {
- 'distros': self.__xmlrpc().get_distros(),
+ 'distros': self.remote.get_distros(),
'ksfiles': self.__ksfiles()
} )
@@ -205,8 +247,9 @@ class CobblerWeb(object):
} )
def __ksfiles(self):
- ksfiles = list()
- for profile in self.__xmlrpc().get_profiles():
+ self.__xmlrpc_setup()
+ ksfiles = []
+ for profile in self.remote.get_profiles():
ksfile = profile['kickstart']
if not ksfile in ksfiles:
ksfiles.append( ksfile )