@@ -32,6 +32,10 @@ def debug(msg):
3232 from sys import stderr
3333 stderr .write ('%s\n ' % msg )
3434
35+ def warn (msg ):
36+ from sys import stderr
37+ stderr .write ('Warning: %s\n ' % msg )
38+
3539class NotApplicableError (Exception ):
3640 """
3741 Exception to be raised if a rule is not applicable for the desired output
@@ -95,22 +99,26 @@ class TimeStampMustBeUpdated(ConversionRule):
9599 root .find ('date' ).text = datetime .utcnow ().strftime ('%Y-%m-%dT%H:%M:%SZ' )
96100
97101class ValueMapsMustNotBeExported (ConversionRule ):
98- """Rule to remove value map definitions from templates older than 3.0"""
102+ """
103+ Rule to remove value map definitions from templates older than 3.0.0
104+ """
99105
100106 def __str__ (self ):
101- return 'Value map definitions must not be exported'
107+ return 'Value map definitions must not be exported before 3.0.0 '
102108
103109 def apply (self ):
104110 if self .versioncmp ('3' ) >= 0 :
105111 raise NotApplicableError ()
106112
107- root .remove (root .find ('value_maps' ))
113+ node = root .find ('value_maps' )
114+ if node is not None :
115+ root .remove (node )
108116
109117class ValueMapsMustNotBeReferenced (ConversionRule ):
110118 """Rule to remove references to value maps"""
111119
112120 def __str__ (self ):
113- return 'References to value maps must not exist '
121+ return 'Value maps must not be used if value map squashing is enabled before 3.0.0 '
114122
115123 def apply (self ):
116124 if not args .squash_value_maps or self .versioncmp ('3' ) >= 0 :
@@ -120,6 +128,55 @@ class ValueMapsMustNotBeReferenced(ConversionRule):
120128 for node in self .root .findall ('.//%s/valuemap' % itemtype ):
121129 node .clear ()
122130
131+ class FixDiscoveryRuleFilters (ConversionRule ):
132+ """
133+ Rule to ensure discovery rule filters comply with the new format introduced
134+ in 2.3.0 via ZBXNEXT-581
135+ """
136+
137+ def __str__ (self ):
138+ return 'Discovery rule filters must use a single expression until 2.4.0'
139+
140+ def apply (self ):
141+ if self .versioncmp ('2.4.0' ) < 0 :
142+ # try convert a multi-filter into a single filter string
143+ for discovery_rule in root .findall ('.//discovery_rule' ):
144+ discovery_rule_name = discovery_rule .find ('name' ).text
145+ node = discovery_rule .find ('filter' )
146+
147+ # check if multi-filter can be downgraded to filter expression
148+ if (
149+ node .find ('evaltype' ).text == '0'
150+ and node .find ('formula' ).text is None
151+ ):
152+ conditions = node .find ('conditions' )
153+
154+ if len (conditions ) == 0 :
155+ # default blank filter
156+ node .clear ()
157+
158+ elif len (conditions ) > 1 :
159+ # multi-filter has too many conditions
160+ warn ('filter for discovery rule \' %s\' has multiple conditions and cannot be converted - dropping' % discovery_rule_name )
161+ node .clear ()
162+
163+ else :
164+ condition = conditions [0 ]
165+ if (
166+ condition .findtext ('.//operator' ) == '8'
167+ and condition .findtext ('.//formulaid' ) == 'A'
168+ ):
169+ # convert to filter expression
170+ filter_str = '%s:%s' % (condition .findtext ('macro' ), condition .findtext ('value' ))
171+ node .clear ()
172+ node .text = filter_str
173+ else :
174+ # unsupported operator or formula id
175+ warn ('filter condition for discovery rule \' %s\' uses an operator or formula ID that cannot be converted - dropping' % discovery_rule_name )
176+ node .clear ()
177+ else :
178+ raise ValueError ('malformed discovery rule filter in \' %s\' ' % discovery_rule_name )
179+
123180# read xml template
124181doc = ET .parse (args .file )
125182root = doc .getroot ()
@@ -137,4 +194,5 @@ for rule in rules:
137194 except NotApplicableError :
138195 pass
139196
140- ET .dump (doc )
197+ # print modified template
198+ ET .dump (doc )
0 commit comments