Source code for cheshire3.server

from __future__ import with_statement

import os

from urlparse import urlsplit

from lxml import etree
from lxml.builder import ElementMaker

from cheshire3.baseObjects import Server
from cheshire3.bootstrap import BSLxmlParser, BootstrapDocument
from cheshire3.configParser import C3Object
from cheshire3.exceptions import (
    ConfigFileException,
    ObjectDoesNotExistException,
    XMLSyntaxError,
    FileSystemException,
    FileDoesNotExistException
)
from cheshire3.internal import cheshire3Root, CONFIG_NS


class SimpleServer(Server):
[docs] databases = {} # here because it's global to the install _possiblePaths = {'sortPath': {"docs": "Path to the 'sort' utility"}} def __init__(self, session, configFile="serverConfig.xml"): # self.defaultFunctionLog = "__api__" self.defaultFunctionLog = "" self.databaseConfigs = {} self.databases = {} self.id = "DefaultServer" session.server = self # Bootstrappage dom = self._getDomFromFile(session, configFile) try: topNode = dom.childNodes[0] except: topNode = dom C3Object.__init__(self, session, topNode, None) # Add default logger to session log = self.get_path(session, 'defaultLogger', None) if log: session.logger = log def _cacheDatabases(self, session): # Read in all Database configurations, build and cache Database objects for dbid in self.databaseConfigs.keys(): db = self.get_object(session, dbid) self.databases[dbid] = db def _get_newDatabaseId(self, session, dbConfig): dbid = dbConfig.attrib.get('id', None) # Check that the identifier is not already in use by existing database try: self.get_object(session, dbid) except ObjectDoesNotExistException: # Doesn't exists, so OK to register it pass else: msg = ("Database with id '{0}' is already registered. " "Please specify a different id in your configurations " "file.".format(dbid)) self.log_critical(session, msg) raise ConfigFileException(msg) return dbid def register_databaseConfigFile(self, session, file_path): """Register a Cheshire3 Database config file. Register a configuration file for a Cheshire3 :py:class:`~cheshire3.baseObjects.Database` with the :py:class:`~cheshire3.baseObjects.Server`. This process simply tells the :py:class:`~cheshire3.baseObjects.Server` that it should include the configuration(s) in your file (it does not ingest your file) so you don't need to re-register when you make changes to the file. """ # Read in proposed config file docFac = self.get_object(session, 'defaultDocumentFactory') docFac.load(session, file_path) confdoc = docFac.get_document(session) try: confrec = BSLxmlParser.process_document(session, confdoc) except XMLSyntaxError as e: msg = ("Config file {0} is not well-formed and valid XML: " "{1}".format(file_path, e.message)) self.log_critical(session, msg) raise ConfigFileException(msg) # Extract the database identifier confdom = confrec.get_dom(session) dbid = self._get_newDatabaseId(session, confdom) if dbid is None: msg = ("Config file {0} must have an 'id' attribute at the " "top-level".format(file_path)) self.log_critical(session, msg) raise ConfigFileException(msg) # Generate plugin XML plugin = E.config( E.subConfigs( E.path( {'type': "database", 'id': dbid}, file_path ) ) ) # Try to do this by writing config plugin file if possible serverDefaultPath = self.get_path(session, 'defaultPath', cheshire3Root) userSpecificPath = os.path.join(os.path.expanduser('~'), '.cheshire3-server') pluginPath = os.path.join('configs', 'databases', '{0}.xml'.format(dbid)) try: pluginfh = open(os.path.join(serverDefaultPath, pluginPath), 'w') except IOError: try: pluginfh = open(os.path.join(userSpecificPath, pluginPath), 'w') except IOError: msg = ("Database plugin directory {0} unavailable for writing" "".format(os.path.join(userSpecificPath, pluginPath))) self.log_critical(session, msg) raise FileSystemException(msg) pluginfh.write( etree.tostring( plugin, pretty_print=True, encoding="utf-8" ) ) pluginfh.close() self.log_info(session, "Database configured in {0} registered with Cheshire3 " "Server {1}".format(file_path, self.id)) def unregister_databaseConfig(self, session, identifier): """Unregister a Cheshire3 Database. Unregister a Cheshire3 :py:class:`~cheshire3.baseObjects.Database` from the :py:class:`~cheshire3.baseObjects.Server`. This process tells the :py:class:`~cheshire3.baseObjects.Server` that it should drop the configuration(s) for the specified `~cheshire3.baseObjects.Database`. """ # Try to do this by writing config plugin file if possible serverDefaultPath = self.get_path(session, 'defaultPath', cheshire3Root ) userSpecificPath = os.path.join(os.path.expanduser('~'), '.cheshire3-server' ) pluginPath = os.path.join('configs', 'databases', '{0}.xml'.format(identifier) ) try: os.remove(os.path.join(userSpecificPath, pluginPath)) except OSError: # File doesn't exist # Try server plugin directory try: os.remove(os.path.join(serverDefaultPath, pluginPath)) except OSError: # File doesn't exist, or insufficient permission if os.path.exists(os.path.join(serverDefaultPath, pluginPath)): msg = ("Insufficient write permissions for Server's " "Database plugin directory" ) else: msg = ("No Database plugin file for Database {0}" "".format(identifier) ) self.log_critical(session, msg) raise FileSystemException(msg) self.log_info(session, "Database {0} unregistered from Cheshire3 " "Server {1}".format(identifier, self.id) ) # Set up ElementMaker for Cheshire3 config namespace E = ElementMaker(namespace=CONFIG_NS, nsmap={None: CONFIG_NS})