def dance(options): from angel_app.config import config AngelConfig = config.getConfig() providerport = AngelConfig.getint("provider", "listenPort") repository = AngelConfig.get("common", "repository") from angel_app.resource.local.external import resource root = resource.External(repository) from twisted.web2 import server from twisted.web2 import channel from twisted.internet import reactor if AngelConfig.getboolean("provider", "useIPv6"): from angel_app.ipv6 import reactor as ignored site = server.Site(root) getLogger().growl("User", "ETERNITY SERVICE", "Started serving on port %s." % providerport) reactor.listenTCP(providerport, channel.HTTPFactory(site), 50) getLogger().info("Listening on port %d and serving content from %s" % (providerport, repository)) # initial test version to integrate a dyndns client into the provider loop dyndnsclient = getCallLaterDynDnsClientForAngelConfig( AngelConfig, callLaterMethod=reactor.callLater, logger=getLogger('dyndns')) if not dyndnsclient is None: reactor.callLater(1, dyndnsclient.check) reactor.run() getLogger().info("Quit")
def boot(): from optparse import OptionParser bootInit() parser = OptionParser() parser.add_option("-d", "--daemon", dest="daemon", help="daemon mode?", default='') parser.add_option("-c", "--config", dest="config", help="alternative config file", default=None) parser.add_option("--no-log-console", dest="no_log_console", help="disable console logging", action="store_true", default=False) (options, dummyargs) = parser.parse_args() appname = "master" # setup/configure config system from angel_app.config.config import getConfig angelConfig = getConfig(options.config) postConfigInit() angelConfig.bootstrapping = False # find out which processes are enabled: options.procsToStart = getProcsToStart(angelConfig) # setup/configure logging from angel_app.log import initializeLogging loghandlers = ['file'] if angelConfig.getboolean('common', 'desktopnotification'): loghandlers.append('growl') if len(options.daemon) == 0 and not options.no_log_console: # not in daemon mode, so we log to console! loghandlers.append('console') initializeLogging(appname, loghandlers) import angel_app.proc.procmanager # import before daemonizing @UnusedImport if len(options.daemon) > 0: from angel_app.proc import daemonizer daemonizer.startstop(action=options.daemon, stdout=appname+'.stdout', stderr=appname+'.stderr', pidfile=appname+'.pid') return options
def dance(options): from angel_app.config import config AngelConfig = config.getConfig() providerport = AngelConfig.getint("provider", "listenPort") repository = AngelConfig.get("common", "repository") from angel_app.resource.local.external import resource root = resource.External(repository) from twisted.web2 import server from twisted.web2 import channel from twisted.internet import reactor if AngelConfig.getboolean("provider", "useIPv6"): from angel_app.ipv6 import reactor as ignored site = server.Site(root) getLogger().growl("User", "ETERNITY SERVICE", "Started serving on port %s." % providerport) reactor.listenTCP(providerport, channel.HTTPFactory(site), 50) getLogger().info("Listening on port %d and serving content from %s" % (providerport, repository)) # initial test version to integrate a dyndns client into the provider loop dyndnsclient = getCallLaterDynDnsClientForAngelConfig(AngelConfig, callLaterMethod = reactor.callLater, logger = getLogger('dyndns')) if not dyndnsclient is None: reactor.callLater(1, dyndnsclient.check) reactor.run() getLogger().info("Quit")
def encrypt(self): """ Replace the contents of the file with the encrypted data, return right away if the resource is a directory or self.secretKey is None. """ if self.fp.isdir() or self.secretKey() == None: return from angel_app.config.config import getConfig from angel_app.singlefiletransaction import SingleFileTransaction try: tmppath = getConfig().get('common', 'repository-tmp') except KeyError: tmppath = None encrypter = self.secretKey() myFile = self.fp.open() t = SingleFileTransaction(tmppath) safe = t.open(self.fp, 'wb') EOF = False bufsize = 1024 # 1 kB encrypter.encStart() while not EOF: data = myFile.read(bufsize) if len(data) > 0: encdata = encrypter.encNext(data) else: encdata = encrypter.encEnd() EOF = True safe.write(encdata) myFile.close() safe.close() t.commit() # TODO: only commit if encryption worked!
def boot(): from optparse import OptionParser bootInit() parser = OptionParser() parser.add_option("-d", "--daemon", dest="daemon", help="daemon mode?", default='') parser.add_option("-c", "--config", dest="config", help="alternative config file", default=None) parser.add_option("-l", "--log", dest="networklogging", help="use network logging?", action="store_true", default=False) (options, dummyargs) = parser.parse_args() # setup/configure config system from angel_app.config.config import getConfig angelConfig = getConfig(options.config) postConfigInit() angelConfig.bootstrapping = False appname = "presenter" # setup/configure logging from angel_app.log import initializeLogging loghandlers = [] # default: no handlers, add as needed below if len(options.daemon) > 0: loghandlers.append('socket') else: if (options.networklogging): loghandlers.append('socket') else: loghandlers.append('console') if angelConfig.getboolean('common', 'desktopnotification'): loghandlers.append('growl') if 'socket' not in loghandlers: # if there is no network logging, then log at least to file: loghandlers.append('file') initializeLogging(appname, loghandlers) if angelConfig.get(appname, 'enable') == False: from angel_app.log import getLogger getLogger().info( "%s process is disabled in the configuration, quitting." % appname) sys.exit(0) if len(options.daemon) > 0: from angel_app.proc import daemonizer daemonizer.startstop(action=options.daemon, stdout=appname + '.stdout', stderr=appname + '.stderr', pidfile=appname + '.pid') return options
def getInitCommands(): lines = forcedShellCommands try: fileName = getConfig().get("gui", "angelshellinit") lines.extend(open(fileName).readlines()) except IOError: # file not found lines.extend(defaultShellCommands) return lines
def startLoggingServer(): """ Will start listening to the configured tcp port using the twisted reactor.listenTCP() call """ factory = Factory() factory.protocol = LoggingProtocol from angel_app.config.config import getConfig angelConfig = getConfig() reactor.listenTCP(angelConfig.getint("common", "loglistenport"), factory)
def getMountTab(): """ Fetches the configured mounts and returns a 2 dimensional list with device - mountpoint values. @return: list of lists """ angelConfig = getConfig() mounttab = [] if angelConfig.has_section('mounttab'): for device in angelConfig.get('mounttab').keys(): mounttab.append((device, angelConfig.get('mounttab', device))) if len(mounttab) < 1: log.debug("No mounts configured in mounttab in configuration") return mounttab
def getMountTab(): """ Fetches the configured mounts and returns a 2 dimensional list with device - mountpoint values. @return: list of lists """ angelConfig = getConfig() mounttab = [] if angelConfig.has_section('mounttab'): for device in angelConfig.get('mounttab').keys(): mounttab.append( (device, angelConfig.get('mounttab', device) ) ) if len(mounttab) < 1: log.debug("No mounts configured in mounttab in configuration") return mounttab
def boot(): bootInit() # setup/configure config system from angel_app.config.config import getConfig angelConfig = getConfig() postConfigInit() angelConfig.bootstrapping = False appname = "gui" # setup/configure logging from angel_app.log import initializeLogging loghandlers = ['file'] # always log to file, no console -> this is a GUI ;-) if angelConfig.getboolean('common', 'desktopnotification'): loghandlers.append('growl') initializeLogging(appname, loghandlers) return True
def boot(): bootInit() # setup/configure config system from angel_app.config.config import getConfig angelConfig = getConfig() postConfigInit() angelConfig.bootstrapping = False appname = "gui" # setup/configure logging from angel_app.log import initializeLogging loghandlers = ['file' ] # always log to file, no console -> this is a GUI ;-) if angelConfig.getboolean('common', 'desktopnotification'): loghandlers.append('growl') initializeLogging(appname, loghandlers) return True
def __putFile(self, stream): """ Write the contents of the request stream to resource's file """ try: tmppath = getConfig().get('common', 'repository-tmp') except KeyError: tmppath = None t = SingleFileTransaction(tmppath) try: safe = t.open(self.fp.path, 'wb') x = waitForDeferred(readIntoFile(stream, safe)) yield x x.getResult() except Exception, e: raise HTTPError( statusForFailure(Failure(), "writing to tmpfile: %s" % (safe.path, )))
def boot(): from optparse import OptionParser bootInit() parser = OptionParser() parser.add_option("-d", "--daemon", dest="daemon", help="daemon mode?", default='') parser.add_option("-c", "--config", dest="config", help="alternative config file", default=None) parser.add_option("-l", "--log", dest="networklogging", help="use network logging?", action="store_true", default=False) (options, dummyargs) = parser.parse_args() # setup/configure config system from angel_app.config.config import getConfig angelConfig = getConfig(options.config) postConfigInit() angelConfig.bootstrapping = False appname = "presenter" # setup/configure logging from angel_app.log import initializeLogging loghandlers = [] # default: no handlers, add as needed below if len(options.daemon) > 0: loghandlers.append('socket') else: if (options.networklogging): loghandlers.append('socket') else: loghandlers.append('console') if angelConfig.getboolean('common', 'desktopnotification'): loghandlers.append('growl') if 'socket' not in loghandlers: # if there is no network logging, then log at least to file: loghandlers.append('file') initializeLogging(appname, loghandlers) if angelConfig.get(appname, 'enable') == False: from angel_app.log import getLogger getLogger().info("%s process is disabled in the configuration, quitting." % appname) sys.exit(0) if len(options.daemon) > 0: from angel_app.proc import daemonizer daemonizer.startstop(action=options.daemon, stdout=appname+'.stdout', stderr=appname+'.stderr', pidfile=appname+'.pid') return options
def __putFile(self, stream): """ Write the contents of the request stream to resource's file """ try: tmppath = getConfig().get('common', 'repository-tmp') except KeyError: tmppath = None t = SingleFileTransaction(tmppath) try: safe = t.open(self.fp.path, 'wb') x = waitForDeferred(readIntoFile(stream, safe)) yield x x.getResult() except Exception, e: raise HTTPError(statusForFailure( Failure(), "writing to tmpfile: %s" % (safe.path,) ))
def dance(options): from angel_app.log import getLogger from angel_app.config import config AngelConfig = config.getConfig() port = AngelConfig.getint("presenter","listenPort") interface = AngelConfig.get("presenter","listenInterface") repository = AngelConfig.get("common","repository") from angel_app.resource.local.internal.resource import Crypto Crypto.rootDirectory = repository root = Crypto(repository) from twisted.web2 import server from twisted.web2 import channel from twisted.internet import reactor site = server.Site(root) reactor.listenTCP(port, channel.HTTPFactory(site), 50, interface) getLogger().info('Listening on IP %s port %d and serving content from %s', interface, port, repository) getLogger().growl("User", "ETERNITY FILE SYSTEM", "Available on port %s." % port) reactor.run() getLogger().info("Quit")
def dance(options): from angel_app.log import getLogger from angel_app.config import config AngelConfig = config.getConfig() port = AngelConfig.getint("presenter", "listenPort") interface = AngelConfig.get("presenter", "listenInterface") repository = AngelConfig.get("common", "repository") from angel_app.resource.local.internal.resource import Crypto Crypto.rootDirectory = repository root = Crypto(repository) from twisted.web2 import server from twisted.web2 import channel from twisted.internet import reactor site = server.Site(root) reactor.listenTCP(port, channel.HTTPFactory(site), 50, interface) getLogger().info('Listening on IP %s port %d and serving content from %s', interface, port, repository) getLogger().growl("User", "ETERNITY FILE SYSTEM", "Available on port %s." % port) reactor.run() getLogger().info("Quit")
def dance(options): from angel_app.log import getLogger from angel_app.config import config from angel_app.maintainer import client from angel_app.admin import initializeRepository log = getLogger("maintainer") log.debug("initializing repository") if not initializeRepository.initializeRepository(): log.warn("Going to quit because initializeRepository failed.") return 1 angelConfig = config.getConfig() repository = angelConfig.get("common", "repository") log.info("starting maintenance loop at '%s'" % repository) log.growl("User", "MAINTENANCE PROCESS", "Started.") try: client.maintenanceLoop() except Exception, e: log.critical("An exception occurred in the maintenance loop", exc_info = e) log.growl("User", "MAINTENANCE PROCESS", "Crash.") return -1
def startProcesses(procsToStart = ['provider', 'presenter', 'maintainer']): """ This method ties together the classes in this module and instantiates/initializes and starts the complete suite of external processes. """ procManager = ExternalProcessManager() procManager.registerProcessStarter(reactor.spawnProcess) procManager.registerDelayedStarter(reactor.callLater) #if binpath == None: binpath = os.getcwd() if "PYTHONPATH" in os.environ.keys(): os.environ["PYTHONPATH"] += ":" + os.sep.join(binpath.split(os.sep)[:-1]) else: os.environ["PYTHONPATH"] = os.sep.join(binpath.split(os.sep)[:-1]) from angel_app.config.config import getConfig angelConfig = getConfig() cfg = angelConfig.getConfigFilename() knownProcessProtocols = { 'provider': ProviderProtocol, 'presenter': PresenterProtocol, 'maintainer': MaintainerProtocol } apps = [] for procToStart in procsToStart: apps.append( (knownProcessProtocols[procToStart](), "%s.py" % procToStart) ) for protocol, scriptName in apps: process = ExternalProcess() process.setProtocol(protocol) # always use the interpreter we were called with process.setExecutable(sys.executable) process.setArgs(args = [sys.executable, os.path.join(binpath, scriptName), '-l', '-c', cfg]) procManager.startServicing(process)
def dance(options): from angel_app.log import getLogger from angel_app.config import config from angel_app.maintainer import client from angel_app.admin import initializeRepository log = getLogger("maintainer") log.debug("initializing repository") if not initializeRepository.initializeRepository(): log.warn("Going to quit because initializeRepository failed.") return 1 angelConfig = config.getConfig() repository = angelConfig.get("common", "repository") log.info("starting maintenance loop at '%s'" % repository) log.growl("User", "MAINTENANCE PROCESS", "Started.") try: client.maintenanceLoop() except Exception, e: log.critical("An exception occurred in the maintenance loop", exc_info=e) log.growl("User", "MAINTENANCE PROCESS", "Crash.") return -1
import os import cPickle import shutil from logging import getLogger from zope.interface import implements from twisted.python.filepath import FilePath from angel_app.config.config import getConfig from angel_app.resource.IDeadPropertyStore import IDeadPropertyStore from angel_app.singlefiletransaction import SingleFileTransaction log = getLogger(__name__) # the root of the angel-app directory tree home = getConfig().get("common","angelhome") # refuse to load the module unless the root exists assert os.path.exists(home), \ "refusing to load the module unless the root exists: " + `home` # where we store file data metadata = home + os.sep + "metadata" if not os.path.exists(metadata): log.info("Creating root directory for meta data: %r", metadata) os.mkdir(metadata) class DirectoryDeadProperties(object): """
import re import logging from twisted.python import log as twistedlog from angel_app.config.config import getConfig DEBUG = False # this will start printing to the console if set to True """ Defaults for the logging backend (RotatingFileHandler) """ log_maxbytes = 1024 * 1024 # each logfile has a max of 1 MB log_backupcount = 7 # max 7 "rotated" logfiles angelConfig = getConfig() loggers = {} appname = "default" # this string is prepended with a trailing dot to all log messages def getLogger(area = ""): """ the most important method in here. Call this to get a logger object, so you can log a message using one of the methods 'error' 'info' 'critical' 'debug' ... See the python 'logging' module documentation for more information. Additionally, this method can be called using an additional parameter called 'area'. The area is used to tag the logged messages, so it is easier to read the log. The value of area really can be any string you like, it might make sense to use for example the class/module name you are in. In logged messages, the area appears just behind the application name, prepended with a dot: "presenter.config" means the log message is from application presenter and area config.
"""Directory listing.""" # system imports import os import urllib import stat import time # twisted imports from twisted.web2 import resource, http, http_headers from angel_app.version import getVersionString from angel_app.tracker.connectToTracker import connectToTracker from angel_app.config.config import getConfig nodename = getConfig().get("maintainer","nodename") CSS = """ <style type="text/css"> <!-- html { height: 100% } body { min-height: 101%; background-color: #ffffff; font-family: Arial, Helvetica, SunSans-Regular, sans-serif; color:#343434; padding:0; margin: 0; border-top: #ff6600 solid 3px; }
""" Routines for synchronizing a local clone with a _single_ remote peer. """ import os import time from logging import getLogger from angel_app import elements from angel_app.singlefiletransaction import SingleFileTransaction from angel_app.io import RateLimit from angel_app.io import bufferedReadLoop from angel_app.config.config import getConfig from angel_app.worker import dowork cfg = getConfig() MAX_DOWNLOAD_SPEED = cfg.getint('common', 'maxdownloadspeed_kib') * 1024 # internally handled in bytes log = getLogger(__name__) def syncContents(resource, referenceClone): """ Synchronize the contents of the resource from the reference clone. """ localpath = resource.fp.path log.debug('syncContents to %r from %r', resource, referenceClone) if referenceClone.isCollection(): # handle directory if resource.exists() and not resource.isCollection(): os.remove(localpath) if not resource.exists(): os.mkdir(localpath) else:
author = """Vincent Kraeutler 2007""" from angel_app.config.config import getConfig from angel_app.log import initializeLogging from angel_app.maintainer import client from angel_app.resource.remote.clone import Clone import unittest import os from angel_app.resource.local.basic import Basic getConfig().container['common']['loglevel'] = 'DEBUG' # global loglevel try: del getConfig().container['logfilters'] except: pass initializeLogging() repositoryPath = getConfig().get("common", "repository") from angel_app.maintainer import mount class CollectTest(unittest.TestCase): def testGetMountTab(self): """ run through """ mount.getMountTab() def testAddMounts(self): """
""" Routines for synchronizing a local clone with a _single_ remote peer. """ import os import time from logging import getLogger from angel_app import elements from angel_app.singlefiletransaction import SingleFileTransaction from angel_app.io import RateLimit from angel_app.io import bufferedReadLoop from angel_app.config.config import getConfig from angel_app.worker import dowork cfg = getConfig() MAX_DOWNLOAD_SPEED = cfg.getint( 'common', 'maxdownloadspeed_kib') * 1024 # internally handled in bytes log = getLogger(__name__) def syncContents(resource, referenceClone): """ Synchronize the contents of the resource from the reference clone. """ localpath = resource.fp.path log.debug('syncContents to %r from %r', resource, referenceClone) if referenceClone.isCollection(): # handle directory if resource.exists() and not resource.isCollection(): os.remove(localpath) if not resource.exists():
def getAngelHomePath(): from angel_app.config.config import getConfig angelConfig = getConfig() angelHomePath = angelConfig.get("common", "angelhome") return angelHomePath
Sizer = wx.BoxSizer(wx.VERTICAL) self.mountsPanel = MountsPanel(self, Log()) Sizer.Add(self.mountsPanel, proportion = 2, flag=wx.ALL|wx.EXPAND, border = 1) self.SetSizer(Sizer) self.Centre() self.Show(True) class Log(object): """ The log output is redirected to the status bar of the containing frame. """ def WriteText(self,text_string): self.write(text_string) def write(self,text_string): wx.GetApp().GetTopWindow().SetStatusText(text_string) if __name__ == '__main__': """ This allows us to run it separately from the rest of the GUI """ from angel_app.log import initializeLogging initializeLogging() app = wx.App(0) app.config = getConfig() MountsWindow(None, -1, _('Mounts')) app.MainLoop()
author = """Vincent Kraeutler 2007""" from angel_app.config.config import getConfig from angel_app.log import initializeLogging from angel_app.maintainer import client from angel_app.resource.remote.clone import Clone import unittest import os from angel_app.resource.local.basic import Basic getConfig().container['common']['loglevel'] = 'DEBUG' # global loglevel try: del getConfig().container['logfilters'] except: pass initializeLogging() repositoryPath = getConfig().get("common","repository") class CollectTest(unittest.TestCase): def testIsMountOfMount(self): """ This test will fail, unless you're vincent. """ polPath = os.sep.join([repositoryPath, "pol"]) polResource = Basic(polPath) #print polResource.children() #print polResource.childLinks().toxml() polM221ePath = os.sep.join([polPath, "MISSION ETERNITY"])
author = """Vincent Kraeutler 2007""" from angel_app.config.config import getConfig from angel_app.log import initializeLogging from angel_app.maintainer import collect from angel_app.resource.remote.clone import Clone import unittest getConfig().container['common']['loglevel'] = 'DEBUG' # global loglevel #del getConfig().container['logfilters'] # get rid of filters initializeLogging() class CollectTest(unittest.TestCase): def testAccessible(self): clone = Clone("missioneternity.org") (cc, acc) = collect.accessible(clone) assert acc assert cc == clone clone2 = Clone("sample.invalid") (cc, acc) = collect.accessible(clone2) assert False == acc assert cc == clone2 def testAcceptable(self): """ Validating a (reachable) clone against itself should always succeed. """ clone = Clone("missioneternity.org")
""" Utilities for creating the default repository directory layout. """ import os import shutil from angel_app.config import config AngelConfig = config.getConfig() def conditionalCreate(path): if not os.path.exists(path): os.mkdir(path) elif not os.path.isdir(path): raise Exception, "Filesystem entry '%s' occupied, cannot create directory here." % path def makeDirectories(): conditionalCreate(AngelConfig.get("common", "angelhome")) conditionalCreate(AngelConfig.get("common", "repository")) conditionalCreate(AngelConfig.get("common", "keyring")) conditionalCreate(AngelConfig.get("common", "logdir")) conditionalCreate( os.path.join(AngelConfig.get("common", "angelhome"), "tmp")) def removeDirectory(name): """ High level method for removing core angel-app directories
from os import sep, listdir from logging import getLogger from angel_app.config.config import getConfig from angel_app.admin import secretKey log = getLogger(__name__) angelConfig = getConfig() # TODO: it seems odd to have one module for a single function. review. # fix: should go into admin/secretKey def loadKeysFromFile(keyDir=secretKey.getKeyringDirectory()): """ Load the ***SECRET*** keys from the appropriate location in the angel-app directory. """ keyFiles = listdir(keyDir) keyRing = {} for fileName in keyFiles: log.info("loading secret key: %r", fileName) angelKey = secretKey.getKeyFor(keyDir + sep + fileName) keyRing[angelKey.exportKey()] = angelKey return keyRing
# See LICENSE for details. """Directory listing.""" # system imports import os import urllib import stat import time # twisted imports from twisted.web2 import resource, http, http_headers from angel_app.version import getVersionString from angel_app.tracker.connectToTracker import connectToTracker from angel_app.config.config import getConfig nodename = getConfig().get("maintainer", "nodename") CSS = """ <style type="text/css"> <!-- html { height: 100% } body { min-height: 101%; background-color: #ffffff; font-family: Arial, Helvetica, SunSans-Regular, sans-serif; color:#343434; padding:0; margin: 0; border-top: #ff6600 solid 3px; }
""" Utility script to force inspect a local resource """ import angel_app.resource.remote.client import angel_app.log angel_app.log.initializeLogging('inspectResource', ['console']) from angel_app.config import config AngelConfig = config.getConfig() repository = AngelConfig.get("common", "repository") if __name__ == "__main__": angel_app.resource.remote.client.inspectResource(repository + "/MISSION ETERNITY")
return a wxwidget with an interactive python shell (has no enclosing window or panel) """ # sort of a joke for now ;-) def getInitCommands(): lines = forcedShellCommands try: fileName = getConfig().get("gui", "angelshellinit") lines.extend(open(fileName).readlines()) except IOError: # file not found lines.extend(defaultShellCommands) return lines onShellLoad = getInitCommands() intro = 'ANGELSHELL %s - EVERYTHING YOU NEED FOR BACKUP' % py.version.VERSION win = py.shell.Shell(parent, -1, introText=intro) for command in onShellLoad: win.Execute(command) return win if __name__ == '__main__': """ This allows us to run it separately from the rest of the GUI """ from angel_app.log import initializeLogging initializeLogging() app = wx.App(0) app.config = getConfig() AngelShellWindow(None, -1, _('Angelshell')) app.MainLoop()