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
7
Merge Requests
7
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
slapos.toolbox
Commits
238b167d
Commit
238b167d
authored
Sep 29, 2016
by
Alain Takoudjou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
monitor: run all promises in a single cron task with timeout of 12 seconds per promises
parent
54399dda
Pipeline
#2443
skipped
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
290 additions
and
188 deletions
+290
-188
slapos/monitor/monitor.py
slapos/monitor/monitor.py
+21
-53
slapos/monitor/runpromise.py
slapos/monitor/runpromise.py
+269
-135
No files found.
slapos/monitor/monitor.py
View file @
238b167d
...
@@ -75,7 +75,7 @@ class Monitoring(object):
...
@@ -75,7 +75,7 @@ class Monitoring(object):
self
.
crond_folder
=
config
.
get
(
"monitor"
,
"crond-folder"
)
self
.
crond_folder
=
config
.
get
(
"monitor"
,
"crond-folder"
)
self
.
logrotate_d
=
config
.
get
(
"monitor"
,
"logrotate-folder"
)
self
.
logrotate_d
=
config
.
get
(
"monitor"
,
"logrotate-folder"
)
self
.
promise_runner
=
config
.
get
(
"monitor"
,
"promise-runner"
)
self
.
promise_runner
=
config
.
get
(
"monitor"
,
"promise-runner"
)
self
.
promise_folder
_list
=
config
.
get
(
"monitor"
,
"promise-folder-list"
).
split
(
)
self
.
promise_folder
=
config
.
get
(
"monitor"
,
"promise-folder"
)
self
.
public_folder
=
config
.
get
(
"monitor"
,
"public-folder"
)
self
.
public_folder
=
config
.
get
(
"monitor"
,
"public-folder"
)
self
.
private_folder
=
config
.
get
(
"monitor"
,
"private-folder"
)
self
.
private_folder
=
config
.
get
(
"monitor"
,
"private-folder"
)
self
.
collector_db
=
config
.
get
(
"monitor"
,
"collector-db"
)
self
.
collector_db
=
config
.
get
(
"monitor"
,
"collector-db"
)
...
@@ -98,10 +98,6 @@ class Monitoring(object):
...
@@ -98,10 +98,6 @@ class Monitoring(object):
self
.
promise_output_file
=
config
.
get
(
"monitor"
,
"promise-output-file"
)
self
.
promise_output_file
=
config
.
get
(
"monitor"
,
"promise-output-file"
)
self
.
bootstrap_is_ok
=
True
self
.
bootstrap_is_ok
=
True
self
.
promise_dict
=
{}
for
promise_folder
in
self
.
promise_folder_list
:
self
.
setupPromiseDictFromFolder
(
promise_folder
)
def
loadConfig
(
self
,
pathes
,
config
=
None
):
def
loadConfig
(
self
,
pathes
,
config
=
None
):
if
config
is
None
:
if
config
is
None
:
config
=
ConfigParser
.
ConfigParser
()
config
=
ConfigParser
.
ConfigParser
()
...
@@ -182,13 +178,6 @@ class Monitoring(object):
...
@@ -182,13 +178,6 @@ class Monitoring(object):
pass
pass
return
configuration_list
return
configuration_list
def
setupPromiseDictFromFolder
(
self
,
folder
):
for
filename
in
os
.
listdir
(
folder
):
path
=
os
.
path
.
join
(
folder
,
filename
)
if
os
.
path
.
isfile
(
path
)
and
os
.
access
(
path
,
os
.
X_OK
):
self
.
promise_dict
[
filename
]
=
{
"path"
:
path
,
"configuration"
:
ConfigParser
.
ConfigParser
()}
def
createSymlinksFromConfig
(
self
,
destination_folder
,
source_path_list
,
name
=
""
):
def
createSymlinksFromConfig
(
self
,
destination_folder
,
source_path_list
,
name
=
""
):
if
destination_folder
:
if
destination_folder
:
if
source_path_list
:
if
source_path_list
:
...
@@ -406,37 +395,30 @@ class Monitoring(object):
...
@@ -406,37 +395,30 @@ class Monitoring(object):
def
generateServiceCronEntries
(
self
):
def
generateServiceCronEntries
(
self
):
# XXX only if at least one configuration file is modified, then write in the cron
# XXX only if at least one configuration file is modified, then write in the cron
#cron_line_list = ['PATH=%s\n' % os.environ['PATH']]
cron_line_list
=
[]
service_name_list
=
[
name
.
replace
(
'.status.json'
,
''
)
service_name_list
=
[
name
.
replace
(
'.status.json'
,
''
)
for
name
in
os
.
listdir
(
self
.
public_folder
)
if
name
.
endswith
(
'.status.json'
)]
for
name
in
os
.
listdir
(
self
.
public_folder
)
if
name
.
endswith
(
'.status.json'
)]
for
service_name
,
promise
in
self
.
promise_items
:
promise_cmd_line
=
[
service_config
=
promise
[
"configuration"
]
"* * * * *"
,
service_status_path
=
"%s/%s.status.json"
%
(
self
.
public_folder
,
service_name
)
"sleep $((1 + RANDOM % 30)) &&"
,
# Sleep between 1 to 30 seconds
mkdirAll
(
os
.
path
.
dirname
(
service_status_path
))
self
.
promise_runner
,
'--pid_path "%s"'
%
os
.
path
.
join
(
self
.
service_pid_folder
,
promise_cmd_line
=
[
"monitor-promises.pid"
),
softConfigGet
(
service_config
,
"service"
,
"frequency"
)
or
"* * * * *"
,
'--output "%s"'
%
self
.
public_folder
,
self
.
promise_runner
,
'--promise_folder "%s"'
%
self
.
promise_folder
,
'--pid_path "%s"'
%
os
.
path
.
join
(
self
.
service_pid_folder
,
'--monitor_url "%s/jio_private/"'
%
self
.
webdav_url
,
# XXX hardcoded,
"%s.pid"
%
service_name
),
'--history_folder "%s"'
%
self
.
public_folder
,
'--output "%s"'
%
service_status_path
,
'--instance_name "%s"'
%
self
.
title
,
'--promise_script "%s"'
%
promise
[
"path"
],
'--hosting_name "%s"'
%
self
.
root_title
]
'--promise_name "%s"'
%
service_name
,
'--monitor_url "%s/jio_private/"'
%
self
.
webdav_url
,
# XXX hardcoded,
registered_promise_list
=
os
.
listdir
(
self
.
promise_folder
)
'--history_folder "%s"'
%
self
.
public_folder
,
for
service_name
in
service_name_list
:
'--instance_name "%s"'
%
self
.
title
,
if
service_name
in
registered_promise_list
:
'--hosting_name "%s"'
%
self
.
root_title
]
cron_line_list
.
append
(
' '
.
join
(
promise_cmd_line
))
if
service_name
in
service_name_list
:
service_name_list
.
pop
(
service_name_list
.
index
(
service_name
))
service_name_list
.
pop
(
service_name_list
.
index
(
service_name
))
if
service_name_list
!=
[]:
if
service_name_list
!=
[]:
# XXX Some service was removed, delete his status file so monitor will not consider
his
status anymore
# XXX Some service was removed, delete his status file so monitor will not consider
the
status anymore
for
service_name
in
service_name_list
:
for
service_name
in
service_name_list
:
status_path
=
os
.
path
.
join
(
self
.
public_folder
,
'%s.status.json'
%
service_name
)
status_path
=
os
.
path
.
join
(
self
.
public_folder
,
'%s.status.json'
%
service_name
)
if
os
.
path
.
exists
(
status_path
):
if
os
.
path
.
exists
(
status_path
):
...
@@ -447,7 +429,7 @@ class Monitoring(object):
...
@@ -447,7 +429,7 @@ class Monitoring(object):
pass
pass
with
open
(
self
.
crond_folder
+
"/monitor-promises"
,
"w"
)
as
fp
:
with
open
(
self
.
crond_folder
+
"/monitor-promises"
,
"w"
)
as
fp
:
fp
.
write
(
"
\
n
"
.
join
(
cron_line_list
))
fp
.
write
(
' '
.
join
(
promise_cmd_line
))
def
addCronEntry
(
self
,
name
,
frequency
,
command
):
def
addCronEntry
(
self
,
name
,
frequency
,
command
):
entry_line
=
'%s %s'
%
(
frequency
,
command
)
entry_line
=
'%s %s'
%
(
frequency
,
command
)
...
@@ -466,21 +448,6 @@ class Monitoring(object):
...
@@ -466,21 +448,6 @@ class Monitoring(object):
self
.
configureFolders
()
self
.
configureFolders
()
# create symlinks from service configurations
self
.
promise_items
=
self
.
promise_dict
.
items
()
for
service_name
,
promise
in
self
.
promise_items
:
service_config
=
promise
[
"configuration"
]
public_path_list
=
softConfigGet
(
service_config
,
"service"
,
"public-path-list"
)
private_path_list
=
softConfigGet
(
service_config
,
"service"
,
"private-path-list"
)
if
public_path_list
:
self
.
createSymlinksFromConfig
(
self
.
public_folder
,
public_path_list
.
split
(),
service_name
)
if
private_path_list
:
self
.
createSymlinksFromConfig
(
self
.
private_folder
,
private_path_list
.
split
(),
service_name
)
# Generate OPML file
# Generate OPML file
self
.
generateOpmlFile
(
self
.
monitor_url_list
,
self
.
generateOpmlFile
(
self
.
monitor_url_list
,
os
.
path
.
join
(
self
.
public_folder
,
'feeds'
))
os
.
path
.
join
(
self
.
public_folder
,
'feeds'
))
...
@@ -514,7 +481,8 @@ class Monitoring(object):
...
@@ -514,7 +481,8 @@ class Monitoring(object):
self
.
generateLogrotateEntry
(
'monitor.service.status'
,
file_list
,
option_list
)
self
.
generateLogrotateEntry
(
'monitor.service.status'
,
file_list
,
option_list
)
# Add cron entry for SlapOS Collect
# Add cron entry for SlapOS Collect
command
=
"%s %s --output_folder %s --collector_db %s"
%
(
self
.
python
,
command
=
"sleep $((1 + RANDOM % 60)) && "
# Random sleep between 1 to 60 seconds
command
+=
"%s %s --output_folder %s --collector_db %s"
%
(
self
.
python
,
self
.
collect_script
,
self
.
data_folder
,
self
.
collector_db
)
self
.
collect_script
,
self
.
data_folder
,
self
.
collector_db
)
self
.
addCronEntry
(
'monitor_collect'
,
'* * * * *'
,
command
)
self
.
addCronEntry
(
'monitor_collect'
,
'* * * * *'
,
command
)
...
...
slapos/monitor/runpromise.py
View file @
238b167d
...
@@ -12,6 +12,9 @@ import glob
...
@@ -12,6 +12,9 @@ import glob
import
argparse
import
argparse
import
traceback
import
traceback
# Promise timeout after 12 seconds
promise_timeout
=
12
def
parseArguments
():
def
parseArguments
():
"""
"""
Parse arguments for monitor collector instance.
Parse arguments for monitor collector instance.
...
@@ -23,6 +26,8 @@ def parseArguments():
...
@@ -23,6 +26,8 @@ def parseArguments():
help
=
'The Path of file where Json result of this promise will be saved.'
)
help
=
'The Path of file where Json result of this promise will be saved.'
)
parser
.
add_argument
(
'--promise_script'
,
parser
.
add_argument
(
'--promise_script'
,
help
=
'Promise script to execute.'
)
help
=
'Promise script to execute.'
)
parser
.
add_argument
(
'--promise_folder'
,
help
=
'Folder where to find promises to execute. Hide --promise_script and --promise_name'
)
parser
.
add_argument
(
'--promise_name'
,
parser
.
add_argument
(
'--promise_name'
,
help
=
'Title to give to this promise.'
)
help
=
'Title to give to this promise.'
)
parser
.
add_argument
(
'--promise_type'
,
parser
.
add_argument
(
'--promise_type'
,
...
@@ -41,147 +46,276 @@ def parseArguments():
...
@@ -41,147 +46,276 @@ def parseArguments():
return
parser
return
parser
def
runpromise
(
parser
):
class
RunPromise
(
object
):
def
__init__
(
self
,
config_parser
):
self
.
config
=
config_parser
def
runpromise
(
self
):
if
self
.
config
.
promise_folder
:
# run all promises from the given folder
return
self
.
runpromise_synchronous
()
if
os
.
path
.
exists
(
self
.
config
.
pid_path
):
with
open
(
self
.
config
.
pid_path
,
"r"
)
as
pidfile
:
try
:
pid
=
int
(
pidfile
.
read
(
6
))
except
ValueError
:
pid
=
None
if
pid
and
os
.
path
.
exists
(
"/proc/"
+
str
(
pid
)):
print
(
"A process is already running with pid "
+
str
(
pid
))
return
1
start_date
=
""
with
open
(
self
.
config
.
pid_path
,
"w"
)
as
pidfile
:
process
=
self
.
executeCommand
(
self
.
config
.
promise_script
)
ps_process
=
psutil
.
Process
(
process
.
pid
)
start_date
=
time
.
strftime
(
"%Y-%m-%d %H:%M:%S"
,
time
.
localtime
(
ps_process
.
create_time
()))
pidfile
.
write
(
str
(
process
.
pid
))
status_json
=
self
.
generateStatusJsonFromProcess
(
process
,
start_date
=
start_date
)
status_json
[
'_links'
]
=
{
"monitor"
:
{
"href"
:
self
.
config
.
monitor_url
}}
status_json
[
'title'
]
=
self
.
config
.
promise_name
status_json
[
'instance'
]
=
self
.
config
.
instance_name
status_json
[
'hosting_subscription'
]
=
self
.
config
.
hosting_name
status_json
[
'type'
]
=
self
.
config
.
promise_type
# Save the lastest status change date (needed for rss)
status_json
[
'change-time'
]
=
ps_process
.
create_time
()
if
os
.
path
.
exists
(
self
.
config
.
output
):
with
open
(
self
.
config
.
output
)
as
f
:
try
:
last_result
=
json
.
loads
(
f
.
read
())
if
status_json
[
'status'
]
==
last_result
[
'status'
]
and
last_result
.
has_key
(
'change-time'
):
status_json
[
'change-time'
]
=
last_result
[
'change-time'
]
except
ValueError
:
pass
self
.
updateStatusHistoryFolder
(
self
.
config
.
promise_name
,
self
.
config
.
output
,
self
.
config
.
history_folder
,
self
.
config
.
promise_type
)
with
open
(
self
.
config
.
output
,
"w"
)
as
outputfile
:
json
.
dump
(
status_json
,
outputfile
)
os
.
remove
(
self
.
config
.
pid_path
)
def
runpromise_synchronous
(
self
):
if
os
.
path
.
exists
(
self
.
config
.
pid_path
):
# Check if another run promise is running
with
open
(
self
.
config
.
pid_path
)
as
fpid
:
try
:
pid
=
int
(
fpid
.
read
(
6
))
except
ValueError
:
pid
=
None
if
pid
and
os
.
path
.
exists
(
"/proc/"
+
str
(
pid
)):
print
(
"A process is already running with pid "
+
str
(
pid
))
return
[]
with
open
(
self
.
config
.
pid_path
,
'w'
)
as
fpid
:
fpid
.
write
(
str
(
os
.
getpid
()))
status_list
=
self
.
checkPromises
(
self
.
config
.
promise_folder
)
promises_status_file
=
os
.
path
.
join
(
self
.
config
.
output
,
'_promise_status'
)
previous_state_dict
=
{}
new_state_dict
=
{}
base_dict
=
{
'_links'
:
{
"monitor"
:
{
"href"
:
self
.
config
.
monitor_url
}},
'instance'
:
self
.
config
.
instance_name
,
'hosting_subscription'
:
self
.
config
.
hosting_name
,
}
if
os
.
path
.
exists
(
promises_status_file
):
with
open
(
promises_status_file
)
as
f
:
try
:
previous_state_dict
=
json
.
loads
(
f
.
read
())
except
ValueError
:
pass
for
status_dict
in
status_list
:
status_dict
.
update
(
base_dict
)
if
previous_state_dict
.
has_key
(
status_dict
[
'title'
]):
status
,
time
=
previous_state_dict
[
status_dict
[
'title'
]].
split
(
'#'
)
if
status_dict
[
'status'
]
==
status
:
status_dict
[
'change-time'
]
=
float
(
time
)
promise_result_file
=
os
.
path
.
join
(
self
.
config
.
output
,
"%s.status.json"
%
status_dict
[
'title'
])
with
open
(
promise_result_file
,
"w"
)
as
outputfile
:
json
.
dump
(
status_dict
,
outputfile
)
new_state_dict
[
status_dict
[
'title'
]]
=
'%s#%s'
%
(
status_dict
[
'status'
],
status_dict
[
'change-time'
])
self
.
updateStatusHistoryFolder
(
status_dict
[
'title'
],
promise_result_file
,
self
.
config
.
history_folder
,
'status'
)
with
open
(
promises_status_file
,
"w"
)
as
outputfile
:
json
.
dump
(
new_state_dict
,
outputfile
)
if
os
.
path
.
exists
(
parser
.
pid_path
):
os
.
remove
(
self
.
config
.
pid_path
)
with
open
(
parser
.
pid_path
,
"r"
)
as
pidfile
:
def
updateStatusHistoryFolder
(
self
,
name
,
status_file
,
history_folder
,
promise_type
):
history_path
=
os
.
path
.
join
(
history_folder
)
if
not
os
.
path
.
exists
(
status_file
):
return
if
not
os
.
path
.
exists
(
history_folder
):
return
if
not
os
.
path
.
exists
(
history_path
):
try
:
try
:
pid
=
int
(
pidfile
.
read
(
6
))
os
.
makedirs
(
history_path
)
except
ValueError
:
except
OSError
,
e
:
pid
=
None
if
e
.
errno
==
os
.
errno
.
EEXIST
and
os
.
path
.
isdir
(
history_path
):
if
pid
and
os
.
path
.
exists
(
"/proc/"
+
str
(
pid
)):
pass
print
(
"A process is already running with pid "
+
str
(
pid
))
else
:
raise
return
1
with
open
(
status_file
,
'r'
)
as
sf
:
start_date
=
""
with
open
(
parser
.
pid_path
,
"w"
)
as
pidfile
:
process
=
executeCommand
(
parser
.
promise_script
)
ps_process
=
psutil
.
Process
(
process
.
pid
)
start_date
=
time
.
strftime
(
"%Y-%m-%d %H:%M:%S"
,
time
.
localtime
(
ps_process
.
create_time
()))
pidfile
.
write
(
str
(
process
.
pid
))
status_json
=
generateStatusJsonFromProcess
(
process
,
start_date
=
start_date
)
status_json
[
'_links'
]
=
{
"monitor"
:
{
"href"
:
parser
.
monitor_url
}}
status_json
[
'title'
]
=
parser
.
promise_name
status_json
[
'instance'
]
=
parser
.
instance_name
status_json
[
'hosting_subscription'
]
=
parser
.
hosting_name
status_json
[
'type'
]
=
parser
.
promise_type
# Save the lastest status change date (needed for rss)
status_json
[
'change-time'
]
=
ps_process
.
create_time
()
if
os
.
path
.
exists
(
parser
.
output
):
with
open
(
parser
.
output
)
as
f
:
try
:
try
:
last_result
=
json
.
loads
(
f
.
read
())
status_dict
=
json
.
loads
(
sf
.
read
())
if
status_json
[
'status'
]
==
last_result
[
'status'
]
and
last_result
.
has_key
(
'change-time'
):
status_json
[
'change-time'
]
=
last_result
[
'change-time'
]
except
ValueError
:
except
ValueError
:
pass
traceback
.
print_exc
()
return
updateStatusHistoryFolder
(
parser
.
promise_name
,
if
promise_type
==
'status'
:
parser
.
output
,
filename
=
'%s.history.json'
%
name
parser
.
history_folder
,
history_file
=
os
.
path
.
join
(
history_path
,
filename
)
parser
.
promise_type
# Remove links from history (not needed)
)
status_dict
.
pop
(
'_links'
,
None
)
with
open
(
parser
.
output
,
"w"
)
as
outputfile
:
if
not
os
.
path
.
exists
(
history_file
):
json
.
dump
(
status_json
,
outputfile
)
with
open
(
history_file
,
'w'
)
as
f_history
:
os
.
remove
(
parser
.
pid_path
)
data_dict
=
{
"date"
:
time
.
time
(),
def
updateStatusHistoryFolder
(
name
,
status_file
,
history_folder
,
promise_type
):
"data"
:
[
status_dict
]
history_path
=
os
.
path
.
join
(
history_folder
)
}
if
not
os
.
path
.
exists
(
status_file
):
f_history
.
write
(
json
.
dumps
(
data_dict
))
return
else
:
if
not
os
.
path
.
exists
(
history_folder
):
# Remove useless informations
return
status_dict
.
pop
(
'hosting_subscription'
,
''
)
if
not
os
.
path
.
exists
(
history_path
):
status_dict
.
pop
(
'title'
,
''
)
try
:
status_dict
.
pop
(
'instance'
,
''
)
os
.
makedirs
(
history_path
)
status_dict
.
pop
(
'type'
,
''
)
except
OSError
,
e
:
if
e
.
errno
==
os
.
errno
.
EEXIST
and
os
.
path
.
isdir
(
history_path
):
pass
else
:
raise
with
open
(
status_file
,
'r'
)
as
sf
:
try
:
status_dict
=
json
.
loads
(
sf
.
read
())
except
ValueError
:
traceback
.
print_exc
()
return
if
promise_type
==
'status'
:
with
open
(
history_file
,
mode
=
"r+"
)
as
f_history
:
filename
=
'%s.history.json'
%
name
f_history
.
seek
(
0
,
2
)
history_file
=
os
.
path
.
join
(
history_path
,
filename
)
position
=
f_history
.
tell
()
-
2
# Remove links from history (not needed)
f_history
.
seek
(
position
)
status_dict
.
pop
(
'_links'
,
None
)
#f_history.write(',%s]}' % str(status_dict))
if
not
os
.
path
.
exists
(
history_file
):
f_history
.
write
(
'%s}'
%
',{}]'
.
format
(
json
.
dumps
(
status_dict
)))
with
open
(
history_file
,
'w'
)
as
f_history
:
elif
promise_type
==
'report'
:
data_dict
=
{
# keep_item_amount = 3
"date"
:
time
.
time
(),
filename
=
'%s.history.json'
%
(
"data"
:
[
status_dict
]
name
)
}
f_history
.
write
(
json
.
dumps
(
data_dict
))
copyfile
(
status_file
,
os
.
path
.
join
(
history_path
,
filename
))
"""# Don't let history foler grow too much, keep xx files
file_list = filter(os.path.isfile,
glob.glob("%s/*.%s.history.json" % (history_path, promise_type))
)
file_count = len(file_list)
if file_count > keep_item_amount:
file_list.sort(key=lambda x: os.path.getmtime(x))
while file_count > keep_item_amount:
to_delete = file_list.pop(0)
try:
os.unlink(to_delete)
file_count -= 1
except OSError:
raise"""
def
generateStatusJsonFromProcess
(
self
,
process
,
start_date
=
None
,
title
=
None
):
stdout
,
stderr
=
process
.
communicate
()
status_json
=
{}
if
process
.
returncode
!=
0
:
status_json
[
"status"
]
=
"ERROR"
else
:
else
:
# Remove useless informations
status_json
[
"status"
]
=
"OK"
status_dict
.
pop
(
'hosting_subscription'
,
''
)
if
stderr
:
status_dict
.
pop
(
'title'
,
''
)
status_json
[
"message"
]
=
stderr
status_dict
.
pop
(
'instance'
,
''
)
elif
stdout
:
status_dict
.
pop
(
'type'
,
''
)
status_json
[
"message"
]
=
stdout
if
start_date
:
with
open
(
history_file
,
mode
=
"r+"
)
as
f_history
:
status_json
[
"start-date"
]
=
start_date
f_history
.
seek
(
0
,
2
)
if
title
:
position
=
f_history
.
tell
()
-
2
status_json
[
"title"
]
=
title
f_history
.
seek
(
position
)
return
status_json
#f_history.write(',%s]}' % str(status_dict))
f_history
.
write
(
'%s}'
%
',{}]'
.
format
(
json
.
dumps
(
status_dict
)))
elif
promise_type
==
'report'
:
def
executeCommand
(
self
,
args
):
# keep_item_amount = 3
return
subprocess
.
Popen
(
filename
=
'%s.history.json'
%
(
args
,
name
)
#cwd=instance_path,
#env=None if sys.platform == 'cygwin' else {},
copyfile
(
status_file
,
os
.
path
.
join
(
history_path
,
filename
))
stdin
=
None
,
"""# Don't let history foler grow too much, keep xx files
stdout
=
subprocess
.
PIPE
,
file_list = filter(os.path.isfile,
stderr
=
subprocess
.
PIPE
glob.glob("%s/*.%s.history.json" % (history_path, promise_type))
)
)
file_count = len(file_list)
def
checkPromises
(
self
,
promise_dir
):
if file_count > keep_item_amount:
"""
file_list.sort(key=lambda x: os.path.getmtime(x))
Run all promises found into specified folder
while file_count > keep_item_amount:
"""
to_delete = file_list.pop(0)
if
not
os
.
path
.
exists
(
promise_dir
)
or
not
os
.
path
.
isdir
(
promise_dir
):
try:
return
[]
os.unlink(to_delete)
file_count -= 1
promise_result_list
=
[]
except OSError:
raise"""
# Check whether every promise is kept
for
promise
in
os
.
listdir
(
promise_dir
):
def
generateStatusJsonFromProcess
(
process
,
start_date
=
None
,
title
=
None
):
stdout
,
stderr
=
process
.
communicate
()
promise_script
=
os
.
path
.
join
(
promise_dir
,
promise
)
status_json
=
{}
if
not
os
.
path
.
isfile
(
promise_script
)
or
not
os
.
access
(
promise_script
,
os
.
X_OK
):
if
process
.
returncode
!=
0
:
# Not executable file
status_json
[
"status"
]
=
"ERROR"
continue
else
:
status_json
[
"status"
]
=
"OK"
command
=
[
promise_script
]
if
stderr
:
promise_name
=
os
.
path
.
basename
(
command
[
0
])
status_json
[
"message"
]
=
stderr
result_dict
=
{
elif
stdout
:
"status"
:
"ERROR"
,
status_json
[
"message"
]
=
stdout
"type"
:
"status"
,
if
start_date
:
"title"
:
promise_name
,
status_json
[
"start-date"
]
=
start_date
"start-date"
:
time
.
strftime
(
"%Y-%m-%d %H:%M:%S"
,
time
.
localtime
(
time
.
time
())),
if
title
:
"change-time"
:
time
.
time
()
status_json
[
"title"
]
=
title
}
return
status_json
process_handler
=
subprocess
.
Popen
(
command
,
stdout
=
subprocess
.
PIPE
,
def
executeCommand
(
args
):
stderr
=
subprocess
.
PIPE
,
return
subprocess
.
Popen
(
stdin
=
subprocess
.
PIPE
)
args
,
process_handler
.
stdin
.
flush
()
#cwd=instance_path,
process_handler
.
stdin
.
close
()
#env=None if sys.platform == 'cygwin' else {},
process_handler
.
stdin
=
None
stdin
=
None
,
stdout
=
subprocess
.
PIPE
,
sleep_time
=
0.1
stderr
=
subprocess
.
PIPE
increment_limit
=
int
(
promise_timeout
/
sleep_time
)
)
for
current_increment
in
range
(
0
,
increment_limit
):
if
process_handler
.
poll
()
is
None
:
time
.
sleep
(
sleep_time
)
continue
if
process_handler
.
poll
()
==
0
:
# Success!
result_dict
[
"message"
]
=
process_handler
.
communicate
()[
0
]
result_dict
[
"status"
]
=
"OK"
else
:
result_dict
[
"message"
]
=
process_handler
.
communicate
()[
1
]
break
else
:
process_handler
.
terminate
()
message
=
process_handler
.
stderr
.
read
()
if
message
is
None
:
message
=
process_handler
.
stdout
.
read
()
or
""
message
+=
'
\
n
PROMISE TIME OUT AFTER %s SECONDS'
%
promise_timeout
result_dict
[
"message"
]
=
message
promise_result_list
.
append
(
result_dict
)
return
promise_result_list
def
main
():
def
main
():
arg_parser
=
parseArguments
()
arg_parser
=
parseArguments
()
sys
.
exit
(
runpromise
(
arg_parser
.
parse_args
()))
promise_runner
=
RunPromise
(
arg_parser
.
parse_args
())
sys
.
exit
(
promise_runner
.
runpromise
())
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