State and Workflow overhaul
===========================
* DONE - Get rid of application.State's current use of backing up
o DONE - have State subclass twisted.persisted.sob.Persistent
o DONE - for regular backups, call monitorStateInstance.save()
note: regular backups are called by a TimerService in the main loop
o DONE - for restoring data, simply use twisted.persisted.sob.load()
* DONE - Rename application.State to application.BaseState (subclassing Persistent)
* DONE - Create application.CheckData, a dictionary with default values
* WON'T DO - Move workflow.ServiceState to application (this belongs where is is for now)
* Plug rules processing into ServiceState methods
* Have monitors subclass ServiceState and override appropriate methods
* DONE - Revamp application.MonitorState
o DONE - __init__() instantiates a CheckState and assigns it to an attribute
o DONE - checkStateInstance gets updated with all service changes; it's the
run-time data for the Monitor
o __init__() instantiates ServiceState and assigns it to an attribute
o ServiceState instance needs to subclass workflow.base.WorkflowAware
o serviceStateInstance needs to have access to checkStateInstance
* Upon monitors parsing/proccessing returned network data:
o monitorStateInstance.workflow.doTrans(this_transition_name)
o doTran() will initiate the actions appropriate for that particular
transition
* DONE - Convert all dictionary access to set/get access:
o DONE - clients/base.py, line 36
Workflow Customizations
=======================
o Move clients.rules.checkForMaintenanceWindow() to pymon.config.
o Implement a very basic flap-guard: don't send out a notice until you
get x fails in a row, y warns in a row, or z errors in a row.
o With notification cut-offs in place, the next thing to implement
is checks for flapping services... that spend less than the cut-off
limit in each state.
o Run some prototype code with Glyph's Q2Q Vertext code... examine if
it's possible to do this via ssh... setting up shared keys between pymon
instances.
o Entirely rip out configuration from globalRegistry -- there's no need
to that to be copied to another object -- it's all available as a
pymon.config import
o Examine methodologies for performing the most checks in the
shortest time; calculate limitations of system (number of hosts,
time to check hosts, max checks in a given interval, etc.)
o Start putting example configurations in the examples directory.
o Rename etc/example-pymon.conf to etc/default-pymon.conf.
o Clean up the print statements (convert to log) in stmp, ftp, and http
text client code.
o Remove all the redundant copying of configuration data into objects
instances and instead use the globalRegistry.
o Standardize repr's of all Monitor objects.
o Add pymon overview page to the web UI
o Add a form in the state lists for entering the number of seconds after
which the page shoudl refresh.
o Convert the meta refrsh of the states web ui to AJAX/JSON.
o Move the hard-coded data structure out of application.State and
put it into code that is reusable. State() should have the flexibility
to be initialized with whatever data structure the user wants.
Ideally, the state data structure should be configurable in pymon.conf.
o There is now state-related information in pymon.application,
pymon.client.base, and pymon.monitors. These need to be consolidated
into some subclass of State() and methods for dealing with this subclass
need to be generalized such that any arbitrary state information can be
stored.
o I would like to add an event system to pymon... events which would
push to a listener. This means that there would be a single place for
doing many sorts of things (like updating state), and any time pymon
would need to update state, it would notify the listener.
o Fix email formatting (only a problem onn some servers... needs
investigation)
o Add https checks
o Add organization to email message and subj; if not org, then host
or IP
o Add a built-in SMTP server for receiving acknowledgements from
users (mail list will be checked for "authorized users"; headers
will be checked for service uri)
o Add custom pymon mail headers to outgoing messages
o Add the ability to disable notifications on a per-service basis
o Get a minimal pymon shell working
o Fix the setuptools bin/script issues
o enable multiple criteria for process matching
o Fix the HTTP NullClient being __call__'ed.
o Make sending of emails in clients.rules.ThresholdRules.sendIt()
non-blocking.
o DONE - Make the loglevel (verbosity) configurable
o DONE - Use log levels for every log message (DEBUG, CRIT, INFO, etc.)
o DONE - Use JSON/AJAX for arbitrarily sorting by columns on the services
web views
o DONE - Fix the maintenance window notification skips; add "maintenance"
to state data structure
o DONE - Add a virtual host monster so that it can be easily integrated
with other web server software
o DONE - Fix the "disabled" service configuration option
o DONE - Add a regular check for config file modifications... re-load
config? This might mean changing the "backup server" to "admin
server", where backups and config file scanning/reloading would be
two of its tasks.
o DONE - Add failed message templates (these were actually already
there for HTTP status checks, there was just a typo in the
schema.xml file.
o DONE - Add notification threshold logic (cutoff based on count
to avoid getting spammed by pymon alerts)
o DONE - Fix the status processing for http_status -- it seems to
be broken
o DONE - Fix the Nevow web interface
o DONE - Get state data backups working for each monitor
o DONE - Fix exceptions with HTTP status failures
o DONE - create valid regex for human-readable ranged values in the
validator pymon.zconfig.rangedValues. This has been moved to an
externall library: adytum.config.zconfig.
o DONE - tweak the ZConfig schema for pymon configuration to go from this:
...
...
...
to something more like this:
...
...
================
Componentization
================
Adapters
--------
Adapt Client to Configuration?
components.registerAdapter(Configuration, SomeClient, IConfigureable)
Adapt Persistent State data to Configuration?
components.registerAdapter(Configuration, State, IConfigureable)
then in the Client, do an interface lookup:
components.globalRegistry(...
Subclassing components.Componentized will let you do stuff like the following:
myclass.setComponent(cfg, IConfigLoader)
myclass.getComponent(...)
IConfigLoader will have to be a custom interface, since
ZConfig.loader.ConfigLoader() doesn't implement an interface. The
Componentized machinery takes care of implementation
(in the fixClassImplements() function):
class IConfigLoader(Interface):
pass
This would provide access to the configuration where ever myclass is
lives. However, this is just the loaded ZConfig configuration -- we want
methods, too. So, we can adapt ZConfig to our config API:
class IPyMonConfigAPI(Interface):
pass
class PyMonConfigAPI(object):
getUri(...)
getServiceDefaults(...)
getAppDefaults(...)
...
class AdaptZConfigToPyMon(object):
implements(IPyMonConfigAPI)
def __init__(self, cfg):
"""
The ZConfig python API is perfect for pymon's needs.
However, there may be other configurations we want to
support in the future; an adaptor for those will have to be
written in order to present an API like ZConfig uses.
For this "adaptor", all we need to do is pass the
configuration object.
"""
self.cfg = cfg
class Configuration(object):
def adapt(self, cfg):
adapted = PyMonConfigAPI(cfg)
self = cfg
Lookups
-------
We need to be able to get instances that implement
* IMonitor
*