work in progress: cybertools.agent - more on base and sample implementations

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2414 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2008-02-24 10:33:26 +00:00
parent c8622b3058
commit f56e98b2ee
16 changed files with 317 additions and 36 deletions

View file

@ -16,28 +16,31 @@ Sub-Packages
============ ============
Top-level Top-level
Generic interfaces, ``tests`` module, this ``README.txt`` file. Generic interfaces, ``commponents``: adapter registry,
``tests`` module, this ``README.txt`` file.
base base
Base and sample classes Base and sample classes.
core core
Agent and scheduling implementations. Agent and scheduling implementations.
control control
Communication with an external agent control and job database application Communication with an external agent control and job database application.
crawl crawl
Scanning/crawling some system, e.g. the database of an email application, Scanning/crawling some system, e.g. the database of an email application,
the local file system, or an external document source the local file system, or an external document source.
transport transport
Transfer of information objects to agents on another machine or Transfer of information objects to agents on another machine or
to an information management application (e.g. loops) to an information management application (e.g. loops).
util util
Various utility modules, e.g. a backport of the Various utility modules, e.g. a backport of the
``twisted.internet.task.coiterate()`` function from Twisted 2.5. ``twisted.internet.task.coiterate()`` function from Twisted 2.5 so that
we can use the Twisted version coming with Zope 3.3.1 for
cybertools.agent.
All sub-packages except ``base`` depend on Twisted. All sub-packages except ``base`` depend on Twisted.
@ -77,7 +80,7 @@ framework Twisted there is some basic stuff (mainly interfaces and
base classes with basic, sample, or dummy implementations) that is base classes with basic, sample, or dummy implementations) that is
independent of Twisted. independent of Twisted.
The code resides in in the ``base`` sub-package. The code for this resides in in the ``base`` sub-package.
Master Agent and Configuration Master Agent and Configuration
------------------------------ ------------------------------
@ -103,24 +106,53 @@ the path to the configuration file.
>>> master.config >>> master.config
controller.name = 'sample' controller.name = 'sample'
logger.name = 'sample' logger.name = 'default'
logger.standard = 20
scheduler.name = 'sample' scheduler.name = 'sample'
Controller Controllers
---------- -----------
Creation of agents and scheduling of jobs is controlled by the controller Creation of agents and scheduling of jobs is controlled by controller
object. This is typically associated with a sort of control storage that objects. These are typically associated with a sort of control storage that
provides agent and job specifications and receives the results of job provides agent and job specifications and receives the results of job
execution. execution.
We open the controller and read in the specifications via the master agent's >>> master.controllers
``setup`` method. [<cybertools.agent.base.control.SampleController object ...>]
We make the contollers provide the specifications via the master agent's
``setup()`` method.
>>> master.setup() >>> master.setup()
Other Agents Other Agents
------------ ------------
The above ``setup()`` call has triggered the creation of one child agent -
that is all the sample controller provides.
>>> master.children
{'sample01': <cybertools.agent.base.agent.SampleAgent object ...>}
Let's check a few attributes of the newly created agent.
>>> agent01 = master.children['sample01']
>>> agent01.master is master
True
>>> agent01.config is master.config
True
Job Scheduling and Execution Job Scheduling and Execution
---------------------------- ----------------------------
>>> master.scheduler
<cybertools.agent.base.schedule.Scheduler object ...>
Logging
-------
>>> master.logger
<cybertools.agent.base.log.Logger object ...>
>>> agent01.logger is master.logger
True

View file

@ -2,3 +2,6 @@
$Id$ $Id$
""" """
# register default adapters
from cybertools.agent.base import agent, control, job, log, schedule

View file

@ -25,6 +25,8 @@ $Id$
from zope.interface import implements from zope.interface import implements
from cybertools.agent.interfaces import IAgent from cybertools.agent.interfaces import IAgent
from cybertools.agent.components import agents
from cybertools.agent.components import controllers, loggers, schedulers
from cybertools.util.config import Configurator from cybertools.util.config import Configurator
@ -33,24 +35,43 @@ class Agent(object):
implements(IAgent) implements(IAgent)
master = None master = None
config = None
logger = None logger = None
def __init__(self, master):
self.master = master
self.config = master.config
self.logger = master.logger
def execute(self, job, params=None): def execute(self, job, params=None):
pass pass
class Master(Agent): class Master(Agent):
config = None
controller = None
scheduler = None scheduler = None
def __init__(self, configuration=None): def __init__(self, configuration=None):
self.config = Configurator() config = self.config = Configurator()
self.master = self
self.controllers = []
self.children = {}
if configuration is not None: if configuration is not None:
self.config.load(configuration) config.load(configuration)
self.logger = loggers(self, name=config.logger.name)
self.controllers.append(controllers(self, name=config.controller.name))
self.scheduler = schedulers(self, name=config.scheduler.name)
def setup(self): def setup(self):
for cont in self.controllers:
cont.setupAgent()
def setupAgents(self, agentSpecs):
for spec in agentSpecs:
agent = agents(self, spec.type)
self.children[spec.name] = agent
def setupJobs(self, jobSpecs):
pass pass
@ -58,3 +79,5 @@ class SampleAgent(Agent):
pass pass
agents.register(SampleAgent, Master, name='sample')

View file

@ -24,6 +24,8 @@ $Id$
from zope.interface import implements from zope.interface import implements
from cybertools.agent.base.agent import Master
from cybertools.agent.components import controllers
from cybertools.agent.interfaces import IController from cybertools.agent.interfaces import IController
@ -31,3 +33,42 @@ class Controller(object):
implements(IController) implements(IController)
def __init__(self, agent):
self.agent = agent
def setupAgent(self):
self.agent.setupAgents(self._getAgents())
self.agent.setupJobs(self._getCurrentJobs())
def _getAgents(self):
return []
def _getCurrentJobs(self):
return []
class SampleController(Controller):
def _getAgents(self):
return [AgentSpecification('sample01', 'sample')]
controllers.register(SampleController, Master, name='sample')
class AgentSpecification(object):
def __init__(self, name, type, **kw):
self.name = name
self.type = type
for k, v in kw.items():
setattr(self, k, v)
class JobSpecification(object):
def __init__(self, name, type, **kw):
self.name = name
self.type = type
for k, v in kw.items():
setattr(self, k, v)

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de # Copyright (c) 2008 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de # Copyright (c) 2008 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -27,7 +27,9 @@ import sys
import time import time
from zope.interface import implements from zope.interface import implements
from loops.agent.interfaces import ILogger, ILogRecord from cybertools.agent.base.agent import Agent
from cybertools.agent.components import loggers
from cybertools.agent.interfaces import ILogger, ILogRecord
class LogRecord(object): class LogRecord(object):
@ -48,20 +50,20 @@ class LogRecord(object):
return ' '.join(msg) return ' '.join(msg)
class Logger(list): class Logger(object):
implements(ILogger) implements(ILogger)
recordFactory = LogRecord recordFactory = LogRecord
def __init__(self, agent): def __init__(self, agent):
self.agent = agent self.agent = agent
self.records = []
self.externalLoggers = []
self.setup() self.setup()
def setup(self): def setup(self):
self.externalLoggers = [] conf = self.agent.config.logger
conf = self.agent.config.logging
if conf.standard: if conf.standard:
logger = logging.getLogger() logger = logging.getLogger()
logger.level = conf.standard logger.level = conf.standard
@ -70,7 +72,9 @@ class Logger(list):
def log(self, data): def log(self, data):
record = self.recordFactory(self, data) record = self.recordFactory(self, data)
self.append(record) self.records.append(record)
for logger in self.externalLoggers: for logger in self.externalLoggers:
logger.info(str(record)) logger.info(str(record))
loggers.register(Logger, Agent, name='default')

View file

@ -6,4 +6,4 @@
controller(name='sample') controller(name='sample')
scheduler(name='sample') scheduler(name='sample')
logger(name='sample') logger(name='default', standard=20)

View file

@ -22,13 +22,20 @@ Basic (sample) job scheduler.
$Id$ $Id$
""" """
from time import time
from zope.interface import implements from zope.interface import implements
from loops.agent.interfaces import IScheduler from cybertools.agent.base.agent import Master
from cybertools.agent.components import schedulers
from cybertools.agent.interfaces import IScheduler
class Scheduler(object): class Scheduler(object):
implements(IScheduler) implements(IScheduler)
def __init__(self, agent):
self.agent = agent
schedulers.register(Scheduler, Master, name='sample')

32
agent/components.py Normal file
View file

@ -0,0 +1,32 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Component registries.
$Id$
"""
from cybertools.util.adapter import AdapterFactory
agents = AdapterFactory()
controllers = AdapterFactory()
jobs = AdapterFactory()
loggers = AdapterFactory()
schedulers = AdapterFactory()

View file

@ -32,8 +32,11 @@ class IAgent(Interface):
""" """
master = Attribute('IMaster instance.') master = Attribute('IMaster instance.')
config = Attribute('Configuration settings.')
logger = Attribute('Logger instance to be used for recording ' logger = Attribute('Logger instance to be used for recording '
'job execution and execution results.') 'job execution and execution results.')
children = Attribute('A collection of agents that are managed by this '
'master.')
def execute(job, params=None): def execute(job, params=None):
""" Execute a job. """ Execute a job.
@ -44,15 +47,30 @@ class IMaster(IAgent):
""" The top-level controller agent. """ The top-level controller agent.
""" """
config = Attribute('Central configuration.') config = Attribute('Central configuration settings.')
controller = Attribute('IController instance.') controllers = Attribute('Collection of IController instances.')
scheduler = Attribute('IScheduler instance.') scheduler = Attribute('IScheduler instance.')
def setup(): def setup():
""" Load agent specifications from the controller and set up """ Set up the master agent by triggering all assigned controllers.
the corresponding agents. Then load the specifications of Each controller will then call the master agent's callback
active jobs from the controller and schedule the corresponding methods ``setupAgents()`` and ``setupJobs()``.
jobs. """
def setupAgents(agentSpecs):
""" Callback for loading agent specifications from the controller
and setting up the corresponding agents.
Will be called upon agent setup and later when the controller
wants to provide new agent information.
"""
def setupJobs(jobSpecs):
""" Callback for loading the specifications of active jobs from
the controller and scheduling the corresponding jobs.
Will be called upon agent setup and later when the controller
wants to provide new job information.
""" """
@ -98,6 +116,11 @@ class IController(Interface):
information. information.
""" """
def setupAgent():
""" Set up the controllers's agent by calling the agent's
callback methods.
"""
class IScheduler(Interface): class IScheduler(Interface):
""" Manages jobs and cares that they are started at the appropriate """ Manages jobs and cares that they are started at the appropriate

27
agent/transport/client.py Normal file
View file

@ -0,0 +1,27 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Transferring information to or requesting information from a remote
cybertools.agent instance with a corresponding server agent.
$Id$
"""
from zope.interface import implements

View file

@ -0,0 +1,4 @@
"""
$Id$
"""

View file

@ -0,0 +1,27 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Transferring files to a remote site via WebDAV.
$Id$
"""
from zope.interface import implements

28
agent/transport/local.py Normal file
View file

@ -0,0 +1,28 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Transferring information to an application on the same machine, typically
a loops site on a local Zope instance.
$Id$
"""
from zope.interface import implements

28
agent/transport/server.py Normal file
View file

@ -0,0 +1,28 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Providing access for remote cybertools.agent instances by listening
for requests from client agents.
$Id$
"""
from zope.interface import implements

View file

@ -53,4 +53,6 @@ class AdapterFactory(object):
check also for its base classes. check also for its base classes.
""" """
adapter = self.queryAdapter(obj, name) adapter = self.queryAdapter(obj, name)
return adapter is not None and adapter(obj) or None if adapter is None:
return None
return adapter(obj)