Hi guys, I managed to model a device scanner based on SA 0.5.2.
Everything works fine on the first run, but when i rerun a scan to
refresh data (specially Client.scantime) i do not see any UPDATE
statement called on clients table.
What's wrong with my design?
Thanks in advance
Massimo
Follow my prog code (more or less)
======================================================
Table definition:
devices = Table('devices', metadata,
Column('id', Integer, primary_key=True),
Column('type', String(10), nullable=False),
Column('hostname', String(20), index=True),
Column('ip', String(15), index=True, unique=True),
Column('scantime', DateTime, default=datetime.now,
onupdate=datetime.now),
Column('sn', String(20)),
Column('model', String(20)),
Column('version', String(20)),
Column('os_id', Integer, ForeignKey('os.id'))
)
clients = Table('clients', metadata,
Column('device_id', Integer, ForeignKey('devices.id'),
primary_key=True),
Column('sidib_id', Integer, ForeignKey('sidib.id')),
Column('last_logon', String(50))
)
servers = Table('servers', metadata,
Column('device_id', Integer, ForeignKey('devices.id'),
primary_key=True),
Column('uptime', String(5))
)
cpu = Table('cpu', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('description', String(50)),
Column('clock_speed', Integer),
Column('socket', String(50)),
UniqueConstraint('name', 'clock_speed', 'description', 'socket',
name='uix_cpu')
)
cpu_device = Table('cpu_device', metadata,
Column('id', Integer, primary_key=True),
Column('device_id', Integer, ForeignKey('devices.id')),
Column('cpu_id', Integer, ForeignKey('cpu.id'))
)
========================================================================
Mapping definition:
#! /usr/bin/env python2.5
# Filename: models.py
'''
Define model and mapping to DB
'''
import logging
import commands
from actions import *
from database import *
from sqlalchemy.orm import relation, reconstructor
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.ext.associationproxy import AssociationProxy
__all__ = ['Client', 'Server']
logger = logging.getLogger(__name__)
def _get_or_create(klass, dic):
logger.debug('_get_or_create(klass=%s, dic=%s)' % (klass, dic))
try:
ret = Session.query(klass).filter_by(**dic).one()
except NoResultFound:
ret = klass(**dic)
logger.debug('Returning %s' % ret)
return ret
class _Mapper(object):
def __init__(self, field, action, class_=None, list=True):
self.field = field
self.class_ = class_
self.action = action
self.list = list
def __repr__(self):
return '''<_Mapper:
\tfield:%s
\tclass_:%s
\taction:%s
\tlist:%s>\n''' % (self.field, self.class_,
self.action, self.list)
class CpuAssociation(object):
def __init__(self, cpu):
self.cpu = cpu
class Device(object):
def __init__(self, ip):
logger.debug('Device.__init__')
self.ip = ip
def isAlive(self):
return commands.ping(self.ip)
def scan(self):
if self.isAlive():
logger.info('Host %s is alive. Start scanning.' % self.ip)
logger.debug('Host %s has %s actions' % (self.ip,
self.actions))
for mapper in self.actions:
func = getattr(commands, mapper.action.command)
funcRet = func(self, mapper.action.param)
logger.debug('Function %s() returned %s' %
(mapper.action.command, funcRet))
if funcRet not in (None, '', []):
if hasattr(mapper.action, 'callback'):
funcRet = mapper.action.callback(funcRet) #
Chiamo l eventuale callback impostata dall azione
if mapper.class_ is not None:
if mapper.list:
funcRet = [_get_or_create(mapper.class_,
ret) for ret in funcRet]
else:
funcRet = _get_or_create(mapper.class_,
funcRet)
setattr(self, mapper.field, funcRet)
logger.debug('Added %s to %s' % (funcRet,
mapper.field))
class Client(Device):
def __init__(self, ip, username, password):
logger.debug('Client.__init__')
Device.__init__(self, ip)
self.username = username
self.password = password
self.setActions()
@reconstructor
def init_on_load(self):
logger.debug('<%s> Client.init_on_load' % self.ip)
self.setActions()
def setActions(self):
self.actions = []
self.actions.append(_Mapper('hostname', GetHostname))
self.actions.append(_Mapper('last_logon', GetLastLogon))
self.actions.append(_Mapper('cpu', GetCPU, Cpu))
cpu = AssociationProxy('cpu_ass', 'cpu', creator=CpuAssociation)
ram = AssociationProxy('ram_ass', 'ram', creator=RamAssociation)
class Server(Device):
def __init__(self, ip, username='', password='',
snmp_community='public'):
Device.__init__(self, ip)
self.username = username
self.password = password
self.snmp_community = snmp_community
self.actions.append(GetHostname)
class Cpu(object):
def __init__(self, **args):
self.__dict__.update(args)
mapper = Session.mapper
mapper(CpuAssociation, cpu_device, properties={
'cpu': relation(Cpu)
}
)
mapper(Device, devices,
polymorphic_on=devices.c.type,
polymorphic_identity='device',
properties={
'os': relation(Os, secondary=os_device, single_parent=True,
cascade='all, delete-orphan')
}
)
mapper(Client, clients,
inherits=Device,
polymorphic_identity='client',
properties={
'sidib': relation(mapper(Sidib, sidib)),
'cpu_ass': relation(CpuAssociation, cascade='all, delete-
orphan')
}
)
mapper(Server, servers,
inherits=Device,
polymorphic_identity='server',
properties={
'cpu_ass': relation(CpuAssociation, cascade='all, delete-
orphan')
}
)
mapper(Cpu, cpu)
=====================================================
Scanner:
#! /usr/bin/env python2.5
# Filename: scanner.py
'''
Manage network device scans
'''
import logging
import workerpool
from datetime import datetime
from pymonit import log
from pymonit.database import metadata, engine, Session
from pymonit.models import Client
logger = logging.getLogger('pymonit')
address = 'xxx.xxx.xxx.%s'
user = 'administrator'
passw = <hidden>
addresses = [address % i for i in range(1,255)]
def action(ip):
try:
host = Session.query(Client).filter_by(ip=ip).one()
host.username = user
host.password = passw
logger.info('Retrieved %s' % host)
except:
host = Client(ip, user, passw)
logger.info('Created %s' % host)
host.scan()
pool = workerpool.WorkerPool(size=10)
pool.map(action, addresses)
pool.shutdown()
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---