Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.toolbox
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Lu Xu
slapos.toolbox
Commits
ed935a62
Commit
ed935a62
authored
Mar 01, 2023
by
Łukasz Nowak
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
check_surykatka_json: Simplify the code a bit
parent
40fd7799
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
70 additions
and
109 deletions
+70
-109
slapos/promise/plugin/check_surykatka_json.py
slapos/promise/plugin/check_surykatka_json.py
+70
-109
No files found.
slapos/promise/plugin/check_surykatka_json.py
View file @
ed935a62
...
@@ -47,112 +47,98 @@ class RunPromise(GenericPromise):
...
@@ -47,112 +47,98 @@ class RunPromise(GenericPromise):
self
.
message_list
.
insert
(
0
,
'%s :'
%
(
url
,))
self
.
message_list
.
insert
(
0
,
'%s :'
%
(
url
,))
emit
(
' '
.
join
(
self
.
message_list
))
emit
(
' '
.
join
(
self
.
message_list
))
def
appendError
(
self
,
message
):
self
.
error
=
True
self
.
message_list
.
extend
([
'ERROR'
,
message
])
def
appendOk
(
self
,
message
):
self
.
message_list
.
extend
([
'OK'
,
message
])
def
senseBotStatus
(
self
):
def
senseBotStatus
(
self
):
key
=
'bot_status'
key
=
'bot_status'
self
.
appendMessage
(
'%s:'
%
(
key
,
))
def
appendError
(
msg
,
*
args
):
self
.
error
=
True
self
.
appendMessage
(
key
+
': ERROR '
+
msg
%
args
)
if
key
not
in
self
.
surykatka_json
:
if
key
not
in
self
.
surykatka_json
:
appendError
(
"%r not in %r"
,
key
,
self
.
json_file
)
self
.
appendError
(
"%r not in %r"
%
(
key
,
self
.
json_file
)
)
return
return
bot_status_list
=
self
.
surykatka_json
[
key
]
bot_status_list
=
self
.
surykatka_json
[
key
]
if
len
(
bot_status_list
)
==
0
:
if
len
(
bot_status_list
)
==
0
:
appendError
(
"%r empty in %r"
,
key
,
self
.
json_file
)
self
.
appendError
(
"%r empty in %r"
%
(
key
,
self
.
json_file
)
)
return
return
bot_status
=
bot_status_list
[
0
]
bot_status
=
bot_status_list
[
0
]
if
bot_status
.
get
(
'text'
)
!=
'loop'
:
if
bot_status
.
get
(
'text'
)
!=
'loop'
:
appendError
(
self
.
appendError
(
"bot_status is %r instead of 'loop' in %r"
,
"bot_status is %r instead of 'loop' in %r"
%
(
str
(
str
(
bot_status
.
get
(
'text'
)),
self
.
json_file
)
bot_status
.
get
(
'text'
)),
self
.
json_file
)
)
return
return
timetuple
=
email
.
utils
.
parsedate
(
bot_status
[
'date'
])
timetuple
=
email
.
utils
.
parsedate
(
bot_status
[
'date'
])
last_bot_datetime
=
datetime
.
datetime
.
fromtimestamp
(
time
.
mktime
(
timetuple
))
last_bot_datetime
=
datetime
.
datetime
.
fromtimestamp
(
time
.
mktime
(
timetuple
))
delta
=
self
.
utcnow
-
last_bot_datetime
delta
=
self
.
utcnow
-
last_bot_datetime
# sanity check
# sanity check
if
delta
<
datetime
.
timedelta
(
minutes
=
0
):
if
delta
<
datetime
.
timedelta
(
minutes
=
0
):
appendError
(
'Last bot datetime is in future'
)
self
.
appendError
(
'Last bot datetime is in future'
)
return
return
if
delta
>
datetime
.
timedelta
(
minutes
=
15
):
if
delta
>
datetime
.
timedelta
(
minutes
=
15
):
appendError
(
'Last bot datetime is more than 15 minutes old'
)
self
.
appendError
(
'Last bot datetime is more than 15 minutes old'
)
return
return
self
.
append
Message
(
'%s: OK Last bot status'
%
(
key
,)
)
self
.
append
Ok
(
'Last bot status'
)
def
senseSslCertificate
(
self
):
def
senseSslCertificate
(
self
):
key
=
'ssl_certificate'
key
=
'ssl_certificate'
self
.
appendMessage
(
'%s:'
%
(
key
,
))
def
appendError
(
msg
,
*
args
):
self
.
error
=
True
self
.
appendMessage
(
key
+
': ERROR '
+
msg
%
args
)
url
=
self
.
getConfig
(
'url'
)
url
=
self
.
getConfig
(
'url'
)
parsed_url
=
urlparse
(
url
)
parsed_url
=
urlparse
(
url
)
if
parsed_url
.
scheme
==
'https'
:
if
parsed_url
.
scheme
==
'https'
:
hostname
=
parsed_url
.
netloc
hostname
=
parsed_url
.
netloc
ssl_check
=
True
certificate_expiration_days
=
self
.
getConfig
(
certificate_expiration_days
=
self
.
getConfig
(
'certificate-expiration-days'
,
'15'
)
'certificate-expiration-days'
,
'15'
)
try
:
try
:
certificate_expiration_days
=
int
(
certificate_expiration_days
)
certificate_expiration_days
=
int
(
certificate_expiration_days
)
except
ValueError
:
except
ValueError
:
certificate_expiration_days
=
None
self
.
appendError
(
'certificate-expiration-days %r is incorrect'
%
(
self
.
getConfig
(
'certificate-expiration-days'
)))
else
:
else
:
ssl_check
=
False
self
.
appendOk
(
'No check needed'
)
certificate_expiration_days
=
None
if
not
ssl_check
:
self
.
appendMessage
(
'%s: OK No check needed'
%
(
key
,))
return
if
certificate_expiration_days
is
None
:
appendError
(
'certificate-expiration-days %r is incorrect'
,
self
.
getConfig
(
'certificate-expiration-days'
))
return
return
if
not
hostname
:
if
not
hostname
:
appendError
(
'url is incorrect'
)
self
.
appendError
(
'url is incorrect'
)
return
return
if
key
not
in
self
.
surykatka_json
:
if
key
not
in
self
.
surykatka_json
:
appendError
(
self
.
appendError
(
'No key %r. If the error persist, please update surykatka.'
%
(
key
,))
'No key %r. If the error persist, please update surykatka.'
%
(
key
,))
return
return
entry_list
=
[
entry_list
=
[
q
for
q
in
self
.
surykatka_json
[
key
]
if
q
[
'hostname'
]
==
hostname
]
q
for
q
in
self
.
surykatka_json
[
key
]
if
q
[
'hostname'
]
==
hostname
]
if
len
(
entry_list
)
==
0
:
if
len
(
entry_list
)
==
0
:
appendError
(
'No data'
)
self
.
appendError
(
'No data'
)
return
return
if
len
(
entry_list
)
>
0
:
self
.
appendMessage
(
'%s:'
%
(
key
,))
def
addError
(
msg
,
*
args
):
self
.
error
=
True
self
.
appendMessage
(
'ERROR '
+
msg
%
args
)
for
entry
in
sorted
(
entry_list
,
key
=
operator
.
itemgetter
(
'ip'
)):
for
entry
in
sorted
(
entry_list
,
key
=
operator
.
itemgetter
(
'ip'
)):
timetuple
=
email
.
utils
.
parsedate
(
entry
[
'not_after'
])
timetuple
=
email
.
utils
.
parsedate
(
entry
[
'not_after'
])
if
timetuple
is
None
:
if
timetuple
is
None
:
ad
dError
(
'IP %s no information'
%
(
entry
[
'ip'
],))
self
.
appen
dError
(
'IP %s no information'
%
(
entry
[
'ip'
],))
else
:
else
:
certificate_expiration_time
=
datetime
.
datetime
.
fromtimestamp
(
certificate_expiration_time
=
datetime
.
datetime
.
fromtimestamp
(
time
.
mktime
(
timetuple
))
time
.
mktime
(
timetuple
))
if
certificate_expiration_time
-
datetime
.
timedelta
(
if
certificate_expiration_time
-
datetime
.
timedelta
(
days
=
certificate_expiration_days
)
<
self
.
utcnow
:
days
=
certificate_expiration_days
)
<
self
.
utcnow
:
ad
dError
(
self
.
appen
dError
(
'IP %s will expire in < %s days'
,
'IP %s will expire in < %s days'
%
(
entry
[
'ip'
],
certificate_expiration_days
)
entry
[
'ip'
],
certificate_expiration_days
)
)
else
:
else
:
self
.
append
Message
(
self
.
append
Ok
(
'
OK
IP %s will expire in > %s days'
%
(
'IP %s will expire in > %s days'
%
(
entry
[
'ip'
],
certificate_expiration_days
))
entry
[
'ip'
],
certificate_expiration_days
))
def
senseHttpQuery
(
self
):
def
senseHttpQuery
(
self
):
key
=
'http_query'
key
=
'http_query'
self
.
appendMessage
(
'%s:'
%
(
key
,
))
def
appendError
(
msg
,
*
args
):
self
.
error
=
True
self
.
appendMessage
(
key
+
': ERROR '
+
msg
%
args
)
if
key
not
in
self
.
surykatka_json
:
if
key
not
in
self
.
surykatka_json
:
appendError
(
"%r not in %r"
,
key
,
self
.
json_file
)
self
.
appendError
(
"%r not in %r"
%
(
key
,
self
.
json_file
)
)
return
return
url
=
self
.
getConfig
(
'url'
)
url
=
self
.
getConfig
(
'url'
)
...
@@ -161,13 +147,9 @@ class RunPromise(GenericPromise):
...
@@ -161,13 +147,9 @@ class RunPromise(GenericPromise):
entry_list
=
[
q
for
q
in
self
.
surykatka_json
[
key
]
if
q
[
'url'
]
==
url
]
entry_list
=
[
q
for
q
in
self
.
surykatka_json
[
key
]
if
q
[
'url'
]
==
url
]
if
len
(
entry_list
)
==
0
:
if
len
(
entry_list
)
==
0
:
appendError
(
'No data'
)
self
.
appendError
(
'No data'
)
return
return
def
addError
(
msg
,
*
args
):
self
.
error
=
True
self
.
appendMessage
(
'ERROR '
+
msg
%
args
)
self
.
appendMessage
(
'%s:'
%
(
key
,))
for
entry
in
sorted
(
entry_list
,
key
=
operator
.
itemgetter
(
'ip'
)):
for
entry
in
sorted
(
entry_list
,
key
=
operator
.
itemgetter
(
'ip'
)):
entry_status_code
=
str
(
entry
[
'status_code'
])
entry_status_code
=
str
(
entry
[
'status_code'
])
if
entry_status_code
!=
status_code
:
if
entry_status_code
!=
status_code
:
...
@@ -178,33 +160,30 @@ class RunPromise(GenericPromise):
...
@@ -178,33 +160,30 @@ class RunPromise(GenericPromise):
entry_status_code
,
status_code_explanation
)
entry_status_code
,
status_code_explanation
)
else
:
else
:
status_code_explanation
=
entry_status_code
status_code_explanation
=
entry_status_code
ad
dError
(
self
.
appen
dError
(
'IP %s expected status_code %s != %s'
%
(
'IP %s expected status_code %s != %s'
%
(
entry
[
'ip'
],
status_code_explanation
,
status_code
))
entry
[
'ip'
],
status_code_explanation
,
status_code
))
else
:
else
:
self
.
append
Message
(
self
.
append
Ok
(
'
OK
IP %s status_code %s'
%
(
entry
[
'ip'
],
status_code
))
'IP %s status_code %s'
%
(
entry
[
'ip'
],
status_code
))
if
http_header_dict
:
if
http_header_dict
:
if
http_header_dict
!=
entry
[
'http_header_dict'
]:
if
http_header_dict
!=
entry
[
'http_header_dict'
]:
ad
dError
(
self
.
appen
dError
(
'IP %s expected HTTP Header %s != of %s'
%
(
'IP %s expected HTTP Header %s != of %s'
%
(
entry
[
'ip'
],
entry
[
'ip'
],
json
.
dumps
(
http_header_dict
,
sort_keys
=
True
),
json
.
dumps
(
http_header_dict
,
sort_keys
=
True
),
json
.
dumps
(
entry
[
'http_header_dict'
],
sort_keys
=
True
)))
json
.
dumps
(
entry
[
'http_header_dict'
],
sort_keys
=
True
)))
else
:
else
:
self
.
append
Message
(
self
.
append
Ok
(
'
OK
IP %s HTTP Header %s'
%
(
'IP %s HTTP Header %s'
%
(
entry
[
'ip'
],
json
.
dumps
(
http_header_dict
,
sort_keys
=
True
)))
entry
[
'ip'
],
json
.
dumps
(
http_header_dict
,
sort_keys
=
True
)))
def
senseDnsQuery
(
self
):
def
senseDnsQuery
(
self
):
key
=
'dns_query'
key
=
'dns_query'
self
.
appendMessage
(
'%s:'
%
(
key
,
))
def
appendError
(
msg
,
*
args
):
self
.
error
=
True
self
.
appendMessage
(
key
+
': ERROR '
+
msg
%
args
)
if
key
not
in
self
.
surykatka_json
:
if
key
not
in
self
.
surykatka_json
:
appendError
(
"%r not in %r"
,
key
,
self
.
json_file
)
self
.
appendError
(
"%r not in %r"
%
(
key
,
self
.
json_file
)
)
return
return
url
=
self
.
getConfig
(
'url'
)
url
=
self
.
getConfig
(
'url'
)
...
@@ -215,36 +194,31 @@ class RunPromise(GenericPromise):
...
@@ -215,36 +194,31 @@ class RunPromise(GenericPromise):
q
for
q
in
self
.
surykatka_json
[
key
]
q
for
q
in
self
.
surykatka_json
[
key
]
if
q
[
'domain'
]
==
hostname
and
q
[
'rdtype'
]
==
'A'
]
if
q
[
'domain'
]
==
hostname
and
q
[
'rdtype'
]
==
'A'
]
if
len
(
entry_list
)
==
0
:
if
len
(
entry_list
)
==
0
:
appendError
(
'No data'
)
self
.
appendError
(
'No data'
)
return
return
self
.
appendMessage
(
'%s:'
%
(
key
,))
if
len
(
ip_set
):
if
len
(
ip_set
):
for
entry
in
sorted
(
entry_list
,
key
=
operator
.
itemgetter
(
'resolver_ip'
)):
for
entry
in
sorted
(
entry_list
,
key
=
operator
.
itemgetter
(
'resolver_ip'
)):
response_ip_set
=
set
([
response_ip_set
=
set
([
q
.
strip
()
for
q
in
entry
[
'response'
].
split
(
","
)
if
q
.
strip
()])
q
.
strip
()
for
q
in
entry
[
'response'
].
split
(
","
)
if
q
.
strip
()])
if
ip_set
!=
response_ip_set
:
if
ip_set
!=
response_ip_set
:
self
.
error
=
True
self
.
appendError
(
self
.
appendMessage
(
"resolver %s expected %s != %s"
%
(
"ERROR resolver %s expected %s != %s"
%
(
entry
[
'resolver_ip'
],
' '
.
join
(
sorted
(
ip_set
)),
entry
[
'resolver_ip'
],
' '
.
join
(
sorted
(
ip_set
)),
' '
.
join
(
sorted
(
response_ip_set
))
or
"empty-reply"
))
' '
.
join
(
sorted
(
response_ip_set
))
or
"empty-reply"
))
else
:
else
:
self
.
append
Message
(
self
.
append
Ok
(
"
OK
resolver %s returned expected set of IPs %s"
%
(
"resolver %s returned expected set of IPs %s"
%
(
entry
[
'resolver_ip'
],
' '
.
join
(
sorted
(
ip_set
)),))
entry
[
'resolver_ip'
],
' '
.
join
(
sorted
(
ip_set
)),))
else
:
else
:
self
.
append
Message
(
'OK
No check configured'
)
self
.
append
Ok
(
'
No check configured'
)
def
senseTcpServer
(
self
):
def
senseTcpServer
(
self
):
key
=
'tcp_server'
key
=
'tcp_server'
self
.
appendMessage
(
'%s:'
%
(
key
,
))
def
appendError
(
msg
,
*
args
):
self
.
error
=
True
self
.
appendMessage
(
key
+
': ERROR '
+
msg
%
args
)
if
key
not
in
self
.
surykatka_json
:
if
key
not
in
self
.
surykatka_json
:
appendError
(
"%r not in %r"
,
key
,
self
.
json_file
)
self
.
appendError
(
"%r not in %r"
%
(
key
,
self
.
json_file
)
)
return
return
url
=
self
.
getConfig
(
'url'
)
url
=
self
.
getConfig
(
'url'
)
...
@@ -264,9 +238,8 @@ class RunPromise(GenericPromise):
...
@@ -264,9 +238,8 @@ class RunPromise(GenericPromise):
if
hostname
in
[
if
hostname
in
[
r
.
strip
()
for
r
in
q
[
'domain'
].
split
(
','
)]
and
q
[
'port'
]
==
port
]
r
.
strip
()
for
r
in
q
[
'domain'
].
split
(
','
)]
and
q
[
'port'
]
==
port
]
if
len
(
entry_list
)
==
0
:
if
len
(
entry_list
)
==
0
:
appendError
(
'No data'
)
self
.
appendError
(
'No data'
)
return
return
self
.
appendMessage
(
'%s:'
%
(
key
,))
if
len
(
ip_set
)
>
0
:
if
len
(
ip_set
)
>
0
:
for
ip
in
sorted
(
ip_set
):
for
ip
in
sorted
(
ip_set
):
ok
=
False
ok
=
False
...
@@ -278,27 +251,21 @@ class RunPromise(GenericPromise):
...
@@ -278,27 +251,21 @@ class RunPromise(GenericPromise):
if
entry
[
'state'
]
==
'open'
:
if
entry
[
'state'
]
==
'open'
:
ok
=
True
ok
=
True
if
ok
:
if
ok
:
self
.
append
Message
(
'OK
IP %s:%s'
%
(
ip
,
port
))
self
.
append
Ok
(
'
IP %s:%s'
%
(
ip
,
port
))
else
:
else
:
self
.
error
=
True
self
.
appendError
(
'IP %s:%s'
%
(
ip
,
port
))
self
.
appendMessage
(
'ERROR IP %s:%s'
%
(
ip
,
port
))
else
:
else
:
self
.
append
Message
(
'OK
No check configured'
)
self
.
append
Ok
(
'
No check configured'
)
def
senseElapsedTime
(
self
):
def
senseElapsedTime
(
self
):
key
=
'elapsed_time'
key
=
'elapsed_time'
self
.
appendMessage
(
'%s:'
%
(
key
,
))
surykatka_key
=
'http_query'
surykatka_key
=
'http_query'
def
appendError
(
msg
,
*
args
):
self
.
error
=
True
self
.
appendMessage
(
'ERROR '
+
msg
%
args
)
if
surykatka_key
not
in
self
.
surykatka_json
:
if
surykatka_key
not
in
self
.
surykatka_json
:
self
.
error
=
True
self
.
appendError
(
self
.
appendMessage
(
'No key %r. If the error persist, please update surykatka.'
%
(
'%s: ERROR No key %r. If the error persist, please update '
surykatka_key
,))
'surykatka.'
%
(
key
,
surykatka_key
,))
return
return
url
=
self
.
getConfig
(
'url'
)
url
=
self
.
getConfig
(
'url'
)
...
@@ -307,10 +274,8 @@ class RunPromise(GenericPromise):
...
@@ -307,10 +274,8 @@ class RunPromise(GenericPromise):
entry_list
=
[
entry_list
=
[
q
for
q
in
self
.
surykatka_json
[
surykatka_key
]
if
q
[
'url'
]
==
url
]
q
for
q
in
self
.
surykatka_json
[
surykatka_key
]
if
q
[
'url'
]
==
url
]
if
len
(
entry_list
)
==
0
:
if
len
(
entry_list
)
==
0
:
self
.
error
=
True
self
.
appendError
(
'No data'
)
self
.
appendMessage
(
'%s: ERROR No data'
%
(
key
,))
return
return
self
.
appendMessage
(
'%s:'
%
(
key
,))
if
maximum_elapsed_time
:
if
maximum_elapsed_time
:
found
=
False
found
=
False
for
entry
in
sorted
(
entry_list
,
key
=
operator
.
itemgetter
(
'ip'
)):
for
entry
in
sorted
(
entry_list
,
key
=
operator
.
itemgetter
(
'ip'
)):
...
@@ -318,40 +283,37 @@ class RunPromise(GenericPromise):
...
@@ -318,40 +283,37 @@ class RunPromise(GenericPromise):
found
=
True
found
=
True
maximum_elapsed_time
=
float
(
maximum_elapsed_time
)
maximum_elapsed_time
=
float
(
maximum_elapsed_time
)
if
entry
[
'total_seconds'
]
==
0.
:
if
entry
[
'total_seconds'
]
==
0.
:
appendError
(
'IP %s failed to reply'
%
(
entry
[
'ip'
]))
self
.
appendError
(
'IP %s failed to reply'
%
(
entry
[
'ip'
]))
elif
entry
[
'total_seconds'
]
>
maximum_elapsed_time
:
elif
entry
[
'total_seconds'
]
>
maximum_elapsed_time
:
appendError
(
self
.
appendError
(
'IP %s replied > %.2fs'
%
'IP %s replied > %.2fs'
%
(
entry
[
'ip'
],
maximum_elapsed_time
))
(
entry
[
'ip'
],
maximum_elapsed_time
))
else
:
else
:
self
.
appendMessage
(
self
.
appendOk
(
'IP %s replied < %.2fs'
%
(
'OK IP %s replied < %.2fs'
%
(
entry
[
'ip'
],
maximum_elapsed_time
))
entry
[
'ip'
],
maximum_elapsed_time
))
if
not
found
:
if
not
found
:
appendError
(
self
.
appendError
(
"No entry with total_seconds found. If the error persist, please "
"No entry with total_seconds found. If the error persist, please "
"update surykatka"
)
"update surykatka"
)
else
:
else
:
self
.
append
Message
(
"OK
No check configured"
)
self
.
append
Ok
(
"
No check configured"
)
def
sense
(
self
):
def
sense
(
self
):
"""
"""
Check if frontend URL is available
Sense various information about the given url
"""
"""
self
.
utcnow
=
datetime
.
datetime
.
utcnow
()
self
.
utcnow
=
datetime
.
datetime
.
utcnow
()
self
.
json_file
=
self
.
getConfig
(
'json-file'
,
''
)
self
.
json_file
=
self
.
getConfig
(
'json-file'
,
''
)
if
not
os
.
path
.
exists
(
self
.
json_file
):
if
not
os
.
path
.
exists
(
self
.
json_file
):
self
.
error
=
True
self
.
appendError
(
'File %r does not exists'
%
self
.
json_file
)
self
.
appendMessage
(
'ERROR File %r does not exists'
%
self
.
json_file
)
else
:
else
:
with
open
(
self
.
json_file
)
as
fh
:
with
open
(
self
.
json_file
)
as
fh
:
try
:
try
:
self
.
surykatka_json
=
json
.
load
(
fh
)
self
.
surykatka_json
=
json
.
load
(
fh
)
except
Exception
:
except
Exception
:
self
.
error
=
True
self
.
appendError
(
self
.
appendMessage
(
"loading JSON from %r"
%
self
.
json_file
)
"ERROR loading JSON from %r"
%
self
.
json_file
)
else
:
else
:
report
=
self
.
getConfig
(
'report'
)
report
=
self
.
getConfig
(
'report'
)
if
report
==
'bot_status'
:
if
report
==
'bot_status'
:
...
@@ -363,9 +325,8 @@ class RunPromise(GenericPromise):
...
@@ -363,9 +325,8 @@ class RunPromise(GenericPromise):
self
.
senseSslCertificate
()
self
.
senseSslCertificate
()
self
.
senseElapsedTime
()
self
.
senseElapsedTime
()
else
:
else
:
self
.
error
=
True
self
.
appendError
(
self
.
appendMessage
(
"Report %r is not supported"
%
report
)
"ERROR Report %r is not supported"
%
report
)
self
.
emitLog
()
self
.
emitLog
()
def
anomaly
(
self
):
def
anomaly
(
self
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment