mirror of
https://github.com/NaN-tic/trytond-monitoring.git
synced 2023-12-14 04:22:59 +01:00
Make synchronization work.
This commit is contained in:
parent
6b446ce807
commit
a7449bb2b8
|
@ -19,6 +19,7 @@ def register():
|
||||||
ResultFloat,
|
ResultFloat,
|
||||||
ResultChar,
|
ResultChar,
|
||||||
AssetPartyNotification,
|
AssetPartyNotification,
|
||||||
|
SynchroMapping,
|
||||||
Asset,
|
Asset,
|
||||||
StateTypeParty,
|
StateTypeParty,
|
||||||
Party,
|
Party,
|
||||||
|
|
335
monitoring.py
335
monitoring.py
|
@ -1,20 +1,35 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains the full
|
# The COPYRIGHT file at the top level of this repository contains the full
|
||||||
# copyright notices and license terms.
|
# copyright notices and license terms.
|
||||||
import sys
|
import sys
|
||||||
import ast
|
#import ast
|
||||||
|
import xmlrpclib
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import hashlib
|
||||||
|
from itertools import izip, chain
|
||||||
|
from decimal import Decimal
|
||||||
|
import logging
|
||||||
|
|
||||||
|
try:
|
||||||
|
import bcrypt
|
||||||
|
except ImportError:
|
||||||
|
bcrypt = None
|
||||||
|
|
||||||
from trytond.tools import safe_eval
|
from trytond.tools import safe_eval
|
||||||
from trytond.model import ModelSQL, ModelView, fields
|
from trytond.model import ModelSQL, ModelView, fields
|
||||||
from trytond.pool import Pool, PoolMeta
|
from trytond.pool import Pool, PoolMeta
|
||||||
from trytond.pyson import Eval
|
from trytond.pyson import Eval
|
||||||
|
from trytond.config import config
|
||||||
|
from trytond.rpc import RPC
|
||||||
|
from trytond.transaction import Transaction
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['CheckType', 'ResultType', 'StateType', 'StateIndicator',
|
__all__ = ['CheckType', 'ResultType', 'StateType', 'StateIndicator',
|
||||||
'StateIndicatorLine', 'Scheduler', 'CheckPlan', 'StateIndicatorCheckPlan',
|
'StateIndicatorLine', 'Scheduler', 'CheckPlan', 'StateIndicatorCheckPlan',
|
||||||
'Check', 'State', 'ResultInteger', 'ResultFloat', 'ResultChar',
|
'Check', 'State', 'ResultInteger', 'ResultFloat', 'ResultChar',
|
||||||
'AssetPartyNotification', 'Asset', 'StateTypeParty', 'Party',
|
'AssetPartyNotification', 'SynchroMapping', 'Asset', 'StateTypeParty',
|
||||||
'RelationType']
|
'Party', 'RelationType']
|
||||||
__metaclass__ = PoolMeta
|
__metaclass__ = PoolMeta
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,6 +146,43 @@ class CheckPlan(ModelSQL, ModelView):
|
||||||
def default_active():
|
def default_active():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_indicators(plan, type_, value):
|
||||||
|
states_to_create = []
|
||||||
|
for indicator in plan.indicators:
|
||||||
|
if indicator.result_type != type_:
|
||||||
|
continue
|
||||||
|
state_type = None
|
||||||
|
for line in indicator.lines:
|
||||||
|
#ast.literal_eval(indicator.expression)
|
||||||
|
if safe_eval(line.expression, {
|
||||||
|
'value': value,
|
||||||
|
}):
|
||||||
|
state_type = line.state_type
|
||||||
|
break
|
||||||
|
if not state_type:
|
||||||
|
state_type = indicator.default_state_type
|
||||||
|
states_to_create.append({
|
||||||
|
'indicator': indicator.id,
|
||||||
|
'state': state_type.id,
|
||||||
|
'value': unicode(value),
|
||||||
|
})
|
||||||
|
return states_to_create
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_indicators(cls, checks):
|
||||||
|
State = Pool().get('monitoring.state')
|
||||||
|
to_create = []
|
||||||
|
for check in checks:
|
||||||
|
for result in chain(check.integer_results, check.float_results,
|
||||||
|
check.char_results):
|
||||||
|
vals = cls.get_indicators(check.plan, result.type,
|
||||||
|
result.value)
|
||||||
|
for state in vals:
|
||||||
|
state['check'] = check.id
|
||||||
|
to_create += vals
|
||||||
|
State.create(to_create)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ModelView.button
|
@ModelView.button
|
||||||
@ModelView.button
|
@ModelView.button
|
||||||
|
@ -179,33 +231,7 @@ class CheckPlan(ModelSQL, ModelView):
|
||||||
% (t.type, result['result']))
|
% (t.type, result['result']))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
states_to_create = []
|
states_to_create = cls.get_indicators(plan, t, value)
|
||||||
for indicator in plan.indicators:
|
|
||||||
if indicator.result_type != t:
|
|
||||||
continue
|
|
||||||
state_type = None
|
|
||||||
for line in indicator.lines:
|
|
||||||
#ast.literal_eval(indicator.expression)
|
|
||||||
if safe_eval(line.expression, {
|
|
||||||
'value': value,
|
|
||||||
}):
|
|
||||||
state_type = line.state_type
|
|
||||||
break
|
|
||||||
if not state_type:
|
|
||||||
state_type = indicator.default_state_type
|
|
||||||
states_to_create.append({
|
|
||||||
'indicator': indicator.id,
|
|
||||||
'state': state_type.id,
|
|
||||||
'value': unicode(value),
|
|
||||||
})
|
|
||||||
# TODO: Should be improved to take into account previous
|
|
||||||
# state and notify if state is ok again
|
|
||||||
|
|
||||||
# Maybe standard triggers will be enough by now
|
|
||||||
#for party in asset.notification_parties:
|
|
||||||
#if state_type in party.notification_types:
|
|
||||||
#Template.render_and_send(configuration.email_template.id, [notification])
|
|
||||||
|
|
||||||
|
|
||||||
to_create.append({
|
to_create.append({
|
||||||
'timestamp': datetime.now(),
|
'timestamp': datetime.now(),
|
||||||
|
@ -251,7 +277,12 @@ class CheckPlan(ModelSQL, ModelView):
|
||||||
"""
|
"""
|
||||||
if self.attributes and name in self.attributes:
|
if self.attributes and name in self.attributes:
|
||||||
return self.attributes[name]
|
return self.attributes[name]
|
||||||
return self.monitored_asset.get_attribute(name)
|
value = None
|
||||||
|
if self.monitored_asset:
|
||||||
|
value = self.monitored_asset.get_attribute(name)
|
||||||
|
if value is None:
|
||||||
|
value = self.monitoring_asset.get_attribute(name)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class StateIndicatorCheckPlan(ModelSQL, ModelView):
|
class StateIndicatorCheckPlan(ModelSQL, ModelView):
|
||||||
|
@ -306,8 +337,6 @@ class StateIndicatorCheckPlan(ModelSQL, ModelView):
|
||||||
return state.color
|
return state.color
|
||||||
|
|
||||||
def get_asset(self, name):
|
def get_asset(self, name):
|
||||||
# TODO: Should probably be replaced by monitored_asset but it is not
|
|
||||||
# required
|
|
||||||
asset = getattr(self.plan, name)
|
asset = getattr(self.plan, name)
|
||||||
if asset:
|
if asset:
|
||||||
return asset.id
|
return asset.id
|
||||||
|
@ -345,7 +374,8 @@ class State(ModelSQL, ModelView):
|
||||||
'Monitoring State'
|
'Monitoring State'
|
||||||
__name__ = 'monitoring.state'
|
__name__ = 'monitoring.state'
|
||||||
_rec_name = 'check'
|
_rec_name = 'check'
|
||||||
check = fields.Many2One('monitoring.check', 'Check', required=True)
|
check = fields.Many2One('monitoring.check', 'Check', required=True,
|
||||||
|
ondelete='CASCADE')
|
||||||
indicator = fields.Many2One('monitoring.state.indicator', 'Indicator',
|
indicator = fields.Many2One('monitoring.state.indicator', 'Indicator',
|
||||||
required=True)
|
required=True)
|
||||||
monitoring_asset = fields.Function(fields.Many2One('asset',
|
monitoring_asset = fields.Function(fields.Many2One('asset',
|
||||||
|
@ -375,7 +405,8 @@ class State(ModelSQL, ModelView):
|
||||||
class ResultInteger(ModelSQL, ModelView):
|
class ResultInteger(ModelSQL, ModelView):
|
||||||
'Monitoring Result Integer'
|
'Monitoring Result Integer'
|
||||||
__name__ = 'monitoring.result.integer'
|
__name__ = 'monitoring.result.integer'
|
||||||
check = fields.Many2One('monitoring.check', 'Check', required=True)
|
check = fields.Many2One('monitoring.check', 'Check', required=True,
|
||||||
|
ondelete='CASCADE')
|
||||||
type = fields.Many2One('monitoring.result.type', 'Type', required=True)
|
type = fields.Many2One('monitoring.result.type', 'Type', required=True)
|
||||||
value = fields.Integer('Value')
|
value = fields.Integer('Value')
|
||||||
uom = fields.Many2One('product.uom', 'UoM', required=True)
|
uom = fields.Many2One('product.uom', 'UoM', required=True)
|
||||||
|
@ -384,7 +415,8 @@ class ResultInteger(ModelSQL, ModelView):
|
||||||
class ResultFloat(ModelSQL, ModelView):
|
class ResultFloat(ModelSQL, ModelView):
|
||||||
'Monitoring Result Float'
|
'Monitoring Result Float'
|
||||||
__name__ = 'monitoring.result.float'
|
__name__ = 'monitoring.result.float'
|
||||||
check = fields.Many2One('monitoring.check', 'Check', required=True)
|
check = fields.Many2One('monitoring.check', 'Check', required=True,
|
||||||
|
ondelete='CASCADE')
|
||||||
type = fields.Many2One('monitoring.result.type', 'Type', required=True)
|
type = fields.Many2One('monitoring.result.type', 'Type', required=True)
|
||||||
value = fields.Float('Value')
|
value = fields.Float('Value')
|
||||||
uom = fields.Many2One('product.uom', 'UoM', required=True)
|
uom = fields.Many2One('product.uom', 'UoM', required=True)
|
||||||
|
@ -393,7 +425,8 @@ class ResultFloat(ModelSQL, ModelView):
|
||||||
class ResultChar(ModelSQL, ModelView):
|
class ResultChar(ModelSQL, ModelView):
|
||||||
'Monitoring Result Char'
|
'Monitoring Result Char'
|
||||||
__name__ = 'monitoring.result.char'
|
__name__ = 'monitoring.result.char'
|
||||||
check = fields.Many2One('monitoring.check', 'Check', required=True)
|
check = fields.Many2One('monitoring.check', 'Check', required=True,
|
||||||
|
ondelete='CASCADE')
|
||||||
type = fields.Many2One('monitoring.result.type', 'Type', required=True)
|
type = fields.Many2One('monitoring.result.type', 'Type', required=True)
|
||||||
value = fields.Char('Value')
|
value = fields.Char('Value')
|
||||||
|
|
||||||
|
@ -405,6 +438,22 @@ class AssetPartyNotification(ModelSQL):
|
||||||
party = fields.Many2One('party.party', 'Party', required=True)
|
party = fields.Many2One('party.party', 'Party', required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class SynchroMapping(ModelSQL):
|
||||||
|
'Synchronization Mapping'
|
||||||
|
__name__ = 'synchro.mapping'
|
||||||
|
local_id = fields.Integer('Local ID', required=True)
|
||||||
|
remote_id = fields.Integer('Remote ID', required=True)
|
||||||
|
model = fields.Char('Model Name', required=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __setup__(cls):
|
||||||
|
super(SynchroMapping, cls).__setup__()
|
||||||
|
cls._sql_constraints += [
|
||||||
|
('remote_id_model_uniq', 'UNIQUE(remote_id, model)',
|
||||||
|
'remote_id and model must be unique.')
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Asset:
|
class Asset:
|
||||||
__name__ = 'asset'
|
__name__ = 'asset'
|
||||||
plans = fields.One2Many('monitoring.check.plan', 'monitoring_asset',
|
plans = fields.One2Many('monitoring.check.plan', 'monitoring_asset',
|
||||||
|
@ -420,6 +469,14 @@ class Asset:
|
||||||
password = fields.Function(fields.Char('Password'), getter='get_password',
|
password = fields.Function(fields.Char('Password'), getter='get_password',
|
||||||
setter='set_password')
|
setter='set_password')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __setup__(cls):
|
||||||
|
super(Asset, cls).__setup__()
|
||||||
|
cls.__rpc__.update({
|
||||||
|
'update_remote_checks': RPC(readonly=False),
|
||||||
|
'fetch_remote_assets': RPC(),
|
||||||
|
})
|
||||||
|
|
||||||
def get_attribute(self, name, browsed=None):
|
def get_attribute(self, name, browsed=None):
|
||||||
"""
|
"""
|
||||||
Returns the value of the given attribute.
|
Returns the value of the given attribute.
|
||||||
|
@ -463,8 +520,6 @@ class Asset:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_login(cls, login):
|
def _get_login(cls, login):
|
||||||
if result:
|
|
||||||
return result
|
|
||||||
cursor = Transaction().cursor
|
cursor = Transaction().cursor
|
||||||
table = cls.__table__()
|
table = cls.__table__()
|
||||||
cursor.execute(*table.select(table.id, table.password_hash,
|
cursor.execute(*table.select(table.id, table.password_hash,
|
||||||
|
@ -539,11 +594,21 @@ class Asset:
|
||||||
return hash_ == bcrypt.hashpw(password, hash_)
|
return hash_ == bcrypt.hashpw(password, hash_)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def object_to_dict(obj):
|
def object_to_dict(obj, mappings=None, model_data=False):
|
||||||
|
ModelData = Pool().get('ir.model.data')
|
||||||
|
if mappings is None:
|
||||||
|
mappings = {}
|
||||||
res = {}
|
res = {}
|
||||||
fields = [name for name, field in obj._fields.iteritems()
|
|
||||||
if isinstance(field, fields.Field)]
|
|
||||||
res['id'] = obj.id
|
res['id'] = obj.id
|
||||||
|
if model_data:
|
||||||
|
records = ModelData.search([
|
||||||
|
('db_id', '=', obj.id),
|
||||||
|
('model', '=', obj.__name__),
|
||||||
|
])
|
||||||
|
value = None
|
||||||
|
if records:
|
||||||
|
value = (records[0].module, records[0].fs_id)
|
||||||
|
res['__model_data__'] = value
|
||||||
for name, field in obj._fields.iteritems():
|
for name, field in obj._fields.iteritems():
|
||||||
value = getattr(obj, name)
|
value = getattr(obj, name)
|
||||||
if isinstance(field, (fields.Function, fields.One2Many,
|
if isinstance(field, (fields.Function, fields.One2Many,
|
||||||
|
@ -554,35 +619,82 @@ class Asset:
|
||||||
elif isinstance(field, fields.Reference) and value:
|
elif isinstance(field, fields.Reference) and value:
|
||||||
# TODO: Reference fields
|
# TODO: Reference fields
|
||||||
value = ''
|
value = ''
|
||||||
|
if name in mappings and value:
|
||||||
|
remote, = SynchroMapping.search([
|
||||||
|
('local_id', '=', value),
|
||||||
|
('model', '=', mappings[name]),
|
||||||
|
])
|
||||||
|
value = remote.remote_id
|
||||||
res[name] = value
|
res[name] = value
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def export_objects(objects):
|
def export_objects(objects, mappings=None, model_data=False):
|
||||||
res = []
|
res = []
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
res.append(cls.object_to_dict(obj))
|
res.append(Asset.object_to_dict(obj, mappings=mappings,
|
||||||
|
model_data=model_data))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dict_to_object(record, cls):
|
def dict_to_object(record, cls, overrides=None, mappings=None):
|
||||||
|
SynchroMapping = Pool().get('synchro.mapping')
|
||||||
|
if overrides is None:
|
||||||
|
overrides = {}
|
||||||
|
if mappings is None:
|
||||||
|
mappings = {}
|
||||||
obj = cls()
|
obj = cls()
|
||||||
for name, value in record.iteritems():
|
for name, value in record.iteritems():
|
||||||
|
if name == '__model_data__':
|
||||||
|
continue
|
||||||
|
value = overrides.get(name, value)
|
||||||
|
if name in mappings and value:
|
||||||
|
local, = SynchroMapping.search([
|
||||||
|
('remote_id', '=', value),
|
||||||
|
('model', '=', mappings[name]),
|
||||||
|
])
|
||||||
|
value = local.local_id
|
||||||
setattr(obj, name, value)
|
setattr(obj, name, value)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def import_objects(records, cls):
|
def import_objects(records, cls, overrides=None, mappings=None):
|
||||||
res = []
|
SynchroMapping = Pool().get('synchro.mapping')
|
||||||
for record in records:
|
ModelData = Pool().get('ir.model.data')
|
||||||
res.append(cls.dict_to_object(record, cls))
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
to_create = []
|
||||||
|
new_records = []
|
||||||
|
map_records = []
|
||||||
|
for record in records:
|
||||||
|
if '__model_data__' in record:
|
||||||
|
value = record['__model_data__']
|
||||||
|
map_records.append({
|
||||||
|
'local_id': ModelData.get_id(value[0], value[1]),
|
||||||
|
'remote_id': record['id'],
|
||||||
|
'model': cls.__name__,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
to_create.append(Asset.dict_to_object(record, cls, overrides, mappings))
|
||||||
|
new_records.append(record)
|
||||||
|
local_objects = cls.create([x._save_values for x in to_create])
|
||||||
|
for local, remote in izip(local_objects, new_records):
|
||||||
|
map_records.append({
|
||||||
|
'local_id': local.id,
|
||||||
|
'remote_id': remote['id'],
|
||||||
|
'model': cls.__name__,
|
||||||
|
})
|
||||||
|
SynchroMapping.create(map_records)
|
||||||
|
return local_objects
|
||||||
|
|
||||||
|
@classmethod
|
||||||
def fetch_remote_assets(cls, login, password):
|
def fetch_remote_assets(cls, login, password):
|
||||||
AssetRelationAll = Pool().get('asset.relation.all')
|
AssetRelationAll = Pool().get('asset.relation.all')
|
||||||
|
ResultType = Pool().get('monitoring.result.type')
|
||||||
|
|
||||||
asset_id = cls.get_login(login, password)
|
asset_id = cls.get_login(login, password)
|
||||||
if not asset_id:
|
if not asset_id:
|
||||||
|
logger.getLogger('monitoring').error('No asset found for login %s' %
|
||||||
|
login)
|
||||||
return
|
return
|
||||||
asset = cls(asset_id)
|
asset = cls(asset_id)
|
||||||
|
|
||||||
|
@ -601,22 +713,25 @@ class Asset:
|
||||||
# assets.append(relation.from_)
|
# assets.append(relation.from_)
|
||||||
plans = []
|
plans = []
|
||||||
schedulers = set()
|
schedulers = set()
|
||||||
types = set()
|
check_types = set()
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
for plan in asset.plans:
|
for plan in asset.plans:
|
||||||
plans.append(plan)
|
plans.append(plan)
|
||||||
schedulers.add(plan.scheduler)
|
schedulers.add(plan.scheduler)
|
||||||
# Types should be available in the remote host
|
check_types.add(plan.type)
|
||||||
#types.add(plan.type)
|
|
||||||
|
result_types = ResultType.search([])
|
||||||
|
|
||||||
data = {}
|
data = {}
|
||||||
data['schedulers'] = cls.export_objects(list(schedulers))
|
data['schedulers'] = cls.export_objects(list(schedulers))
|
||||||
# Types should be available in the remote host
|
data['check_types'] = cls.export_objects(list(check_types),
|
||||||
#data['types'] = cls.export_objects(list(types))
|
model_data=True)
|
||||||
|
data['result_types'] = cls.export_objects(result_types, model_data=True)
|
||||||
data['plans'] = cls.export_objects(plans)
|
data['plans'] = cls.export_objects(plans)
|
||||||
data['assets'] = cls.export_objects(assets)
|
data['assets'] = cls.export_objects(assets)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@classmethod
|
||||||
def update_remote_checks(cls, login, password, data):
|
def update_remote_checks(cls, login, password, data):
|
||||||
if not cls.get_login(login, password):
|
if not cls.get_login(login, password):
|
||||||
return
|
return
|
||||||
|
@ -626,15 +741,109 @@ class Asset:
|
||||||
IntegerResult = pool.get('monitoring.result.integer')
|
IntegerResult = pool.get('monitoring.result.integer')
|
||||||
FloatResult = pool.get('monitoring.result.float')
|
FloatResult = pool.get('monitoring.result.float')
|
||||||
CharResult = pool.get('monitoring.result.char')
|
CharResult = pool.get('monitoring.result.char')
|
||||||
|
CheckPlan = pool.get('monitoring.check.plan')
|
||||||
|
|
||||||
objs = cls.import_objects(data['checks'], Check)
|
# TODO: Result and Check types need to be properly synchronized
|
||||||
Check.save(objs)
|
# Now they work only if modules were installed in the same
|
||||||
cls.import_objects(data['integer_results'], IntegerResult)
|
# order on both ends.
|
||||||
IntegerResult.save(objs)
|
checks = cls.import_objects(data['checks'], Check)
|
||||||
cls.import_objects(data['float_results'], FloatResult)
|
cls.import_objects(data['integer_results'], IntegerResult,
|
||||||
FloatResult.save(objs)
|
mappings={
|
||||||
cls.import_objects(data['char_results'], CharResult)
|
'check': 'monitoring.check',
|
||||||
CharResult.save(objs)
|
})
|
||||||
|
cls.import_objects(data['float_results'], FloatResult,
|
||||||
|
mappings={
|
||||||
|
'check': 'monitoring.check',
|
||||||
|
})
|
||||||
|
cls.import_objects(data['char_results'], CharResult,
|
||||||
|
mappings={
|
||||||
|
'check': 'monitoring.check',
|
||||||
|
})
|
||||||
|
CheckPlan.create_indicators(Check.browse([x.id for x in checks]))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sync(cls):
|
||||||
|
pool = Pool()
|
||||||
|
Check = pool.get('monitoring.check')
|
||||||
|
IntegerResult = pool.get('monitoring.result.integer')
|
||||||
|
FloatResult = pool.get('monitoring.result.float')
|
||||||
|
CharResult = pool.get('monitoring.result.char')
|
||||||
|
Plan = pool.get('monitoring.check.plan')
|
||||||
|
Scheduler = pool.get('monitoring.scheduler')
|
||||||
|
Asset = pool.get('asset')
|
||||||
|
Product = pool.get('product.product')
|
||||||
|
Template = pool.get('product.template')
|
||||||
|
SynchroMapping = pool.get('synchro.mapping')
|
||||||
|
ModelData = pool.get('ir.model.data')
|
||||||
|
CheckType = pool.get('monitoring.check.type')
|
||||||
|
ResultType = pool.get('monitoring.result.type')
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
checks = Check.search([])
|
||||||
|
data['checks'] = cls.export_objects(checks, mappings={
|
||||||
|
'plan': 'monitoring.check.plan',
|
||||||
|
'monitoring_asset': 'asset',
|
||||||
|
'monitored_asset': 'asset',
|
||||||
|
})
|
||||||
|
integers = IntegerResult.search([])
|
||||||
|
data['integer_results'] = cls.export_objects(integers)
|
||||||
|
floats = FloatResult.search([])
|
||||||
|
data['float_results'] = cls.export_objects(floats)
|
||||||
|
chars = CharResult.search([])
|
||||||
|
data['char_results'] = cls.export_objects(chars)
|
||||||
|
|
||||||
|
uri = config.get('monitoring', 'uri')
|
||||||
|
username = config.get('monitoring', 'username')
|
||||||
|
password = config.get('monitoring', 'password')
|
||||||
|
server = xmlrpclib.ServerProxy(uri, allow_none=True)
|
||||||
|
context = server.model.res.user.get_preferences(True, {})
|
||||||
|
server.model.asset.update_remote_checks(username, password, data, context)
|
||||||
|
data = server.model.asset.fetch_remote_assets(username, password, context)
|
||||||
|
|
||||||
|
Check.delete(checks)
|
||||||
|
IntegerResult.delete(checks)
|
||||||
|
FloatResult.delete(checks)
|
||||||
|
CharResult.delete(checks)
|
||||||
|
|
||||||
|
Plan.delete(Plan.search([]))
|
||||||
|
Scheduler.delete(Scheduler.search([]))
|
||||||
|
Asset.delete(Asset.search([]))
|
||||||
|
|
||||||
|
SynchroMapping.delete(SynchroMapping.search([]))
|
||||||
|
|
||||||
|
# TODO: Maybe create a product with the module and deactivate it by
|
||||||
|
# default. The problem would be if another module adds required fields.
|
||||||
|
asset_product = Product.search([
|
||||||
|
('type', '=', 'assets'),
|
||||||
|
('code', '=', 'monitoring'),
|
||||||
|
], limit=1)
|
||||||
|
if not asset_product:
|
||||||
|
asset_product = Template.create([{
|
||||||
|
'name': 'Monitoring Asset',
|
||||||
|
'type': 'assets',
|
||||||
|
'list_price': Decimal(0),
|
||||||
|
'cost_price': Decimal(0),
|
||||||
|
'default_uom': ModelData.get_id('product', 'uom_unit'),
|
||||||
|
'products': [('create', [{
|
||||||
|
'code': 'monitoring',
|
||||||
|
}])]
|
||||||
|
}])
|
||||||
|
asset_product = Product.search([
|
||||||
|
('type', '=', 'assets'),
|
||||||
|
('code', '=', 'monitoring'),
|
||||||
|
], limit=1)
|
||||||
|
asset_product = asset_product[0]
|
||||||
|
cls.import_objects(data['assets'], Asset, overrides={
|
||||||
|
'product': asset_product.id,
|
||||||
|
})
|
||||||
|
cls.import_objects(data['schedulers'], Scheduler)
|
||||||
|
cls.import_objects(data['plans'], Plan, mappings={
|
||||||
|
'monitoring_asset': 'asset',
|
||||||
|
'monitored_asset': 'asset',
|
||||||
|
'scheduler': 'monitoring.scheduler',
|
||||||
|
})
|
||||||
|
cls.import_objects(data['check_types'], CheckType)
|
||||||
|
cls.import_objects(data['result_types'], ResultType)
|
||||||
|
|
||||||
|
|
||||||
class StateTypeParty(ModelSQL):
|
class StateTypeParty(ModelSQL):
|
||||||
|
|
|
@ -790,6 +790,19 @@
|
||||||
<field name="function">check_all</field>
|
<field name="function">check_all</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.cron" id="cron_slave">
|
||||||
|
<field name="name">Monitoring Slave</field>
|
||||||
|
<field name="request_user" ref="res.user_admin"/>
|
||||||
|
<field name="user" ref="user_monitoring"/>
|
||||||
|
<field name="active" eval="True"/>
|
||||||
|
<field name="interval_number">1</field>
|
||||||
|
<field name="interval_type">minutes</field>
|
||||||
|
<field name="number_calls">-1</field>
|
||||||
|
<field name="repeat_missed" eval="False"/>
|
||||||
|
<field name="model">asset</field>
|
||||||
|
<field name="function">sync</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<!-- State Types -->
|
<!-- State Types -->
|
||||||
<record model="monitoring.state.type" id="state_type_ok">
|
<record model="monitoring.state.type" id="state_type_ok">
|
||||||
<field name="name">Ok</field>
|
<field name="name">Ok</field>
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
<data>
|
<data>
|
||||||
<xpath expr="/form/notebook/page[@id='relations']" position="after">
|
<xpath expr="/form/notebook/page[@id='relations']" position="after">
|
||||||
<page string="Monitoring" id="monitoring">
|
<page string="Monitoring" id="monitoring">
|
||||||
|
<label name="login"/>
|
||||||
|
<field name="login"/>
|
||||||
|
<label name="password"/>
|
||||||
|
<field name="password" widget="password"/>
|
||||||
<field name="plans" colspan="4"/>
|
<field name="plans" colspan="4"/>
|
||||||
<field name="notification_parties" colspan="4"/>
|
<field name="notification_parties" colspan="4"/>
|
||||||
<field name="states" colspan="4"/>
|
<field name="states" colspan="4"/>
|
||||||
|
|
Loading…
Reference in a new issue