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
6
Merge Requests
6
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
f78c9d5c
Commit
f78c9d5c
authored
Oct 12, 2012
by
Cédric Le Ninivin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Introducing basic process manager for runner
parent
2a35d1f0
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
136 additions
and
117 deletions
+136
-117
slapos/runner/__init__.py
slapos/runner/__init__.py
+2
-0
slapos/runner/process.py
slapos/runner/process.py
+106
-0
slapos/runner/static/js/scripts/process.js
slapos/runner/static/js/scripts/process.js
+2
-2
slapos/runner/utils.py
slapos/runner/utils.py
+23
-113
slapos/runner/views.py
slapos/runner/views.py
+3
-2
No files found.
slapos/runner/__init__.py
View file @
f78c9d5c
...
@@ -8,6 +8,7 @@ import logging
...
@@ -8,6 +8,7 @@ import logging
import
logging.handlers
import
logging.handlers
from
optparse
import
OptionParser
,
Option
from
optparse
import
OptionParser
,
Option
import
os
import
os
import
slapos.runner.process
import
sys
import
sys
from
slapos.runner.utils
import
runInstanceWithLock
from
slapos.runner.utils
import
runInstanceWithLock
...
@@ -144,5 +145,6 @@ def serve(config):
...
@@ -144,5 +145,6 @@ def serve(config):
if
not
os
.
path
.
exists
(
software_link
):
if
not
os
.
path
.
exists
(
software_link
):
os
.
mkdir
(
software_link
)
os
.
mkdir
(
software_link
)
runInstanceWithLock
(
app
.
config
)
runInstanceWithLock
(
app
.
config
)
slapos
.
runner
.
process
.
setHandler
()
app
.
run
(
host
=
config
.
runner_host
,
port
=
int
(
config
.
runner_port
),
app
.
run
(
host
=
config
.
runner_host
,
port
=
int
(
config
.
runner_port
),
debug
=
config
.
debug
,
threaded
=
True
)
debug
=
config
.
debug
,
threaded
=
True
)
slapos/runner/process.py
0 → 100644
View file @
f78c9d5c
import
os
import
psutil
import
signal
import
subprocess
import
sys
SLAPRUNNER_PROCESS_LIST
=
[]
class
Popen
(
subprocess
.
Popen
):
"""
Extension of Popen to launch and kill process in a clean way
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""
Launch process and add object to process list for handler
"""
self
.
name
=
kwargs
.
pop
(
'name'
,
None
)
kwargs
[
'stdin'
]
=
subprocess
.
PIPE
kwargs
[
'stderr'
]
=
subprocess
.
STDOUT
kwargs
.
setdefault
(
'stdout'
,
subprocess
.
PIPE
)
kwargs
.
setdefault
(
'close_fds'
,
True
)
subprocess
.
Popen
.
__init__
(
self
,
*
args
,
**
kwargs
)
SLAPRUNNER_PROCESS_LIST
.
append
(
self
)
self
.
stdin
.
flush
()
self
.
stdin
.
close
()
self
.
stdin
=
None
def
kill
(
self
,
sig
=
signal
.
SIGTERM
,
recursive
=
False
):
"""
Kill process and all its descendant if recursive
"""
if
self
.
poll
()
is
None
:
if
recursive
:
childs_pids
=
pidppid
(
self
.
pid
)
for
pid
in
childs_pids
:
killNoFail
(
pid
,
sig
)
killNoFail
(
self
.
pid
,
sig
)
if
self
.
poll
()
is
not
None
:
SLAPRUNNER_PROCESS_LIST
.
remove
(
self
)
def
__del__
(
self
):
"""
Del function, try to kill process group
and process if its group does not exist
"""
for
pid
in
(
-
self
.
pid
,
self
.
pid
):
try
:
os
.
kill
(
-
self
.
pid
,
15
)
except
OSError
:
pass
subprocess
.
Popen
.
__del__
(
self
)
def
pidppid
(
pid
,
recursive
=
True
):
"""
Return a list of all children of pid
"""
return
[
p
.
pid
for
p
in
psutil
.
Process
(
pid
).
get_children
(
recursive
=
recursive
)]
def
killNoFail
(
pid
,
sig
):
"""
function to kill without failing. Return True if kill do not fail
"""
try
:
os
.
kill
(
pid
,
sig
)
return
True
except
OSError
:
return
False
def
isRunning
(
name
):
"""
Return True if a process with this name is running
"""
for
process
in
SLAPRUNNER_PROCESS_LIST
:
if
process
.
name
==
name
:
if
process
.
poll
()
is
None
:
return
True
return
False
def
killRunningProcess
(
name
,
recursive
=
False
):
"""
Kill all process with name
"""
for
process
in
SLAPRUNNER_PROCESS_LIST
:
if
process
.
name
==
name
:
process
.
kill
(
recursive
=
recursive
)
def
handler
(
sig
,
frame
):
"""
Signal handler to kill all process
"""
pid
=
os
.
getpid
()
os
.
kill
(
-
pid
,
sig
)
sys
.
exit
()
def
setHandler
(
sig_list
=
None
):
if
sig_list
is
None
:
sig_list
=
[
signal
.
SIGTERM
]
for
sig
in
sig_list
:
signal
.
signal
(
sig
,
handler
)
slapos/runner/static/js/scripts/process.js
View file @
f78c9d5c
...
@@ -83,10 +83,10 @@ function stopProcess() {
...
@@ -83,10 +83,10 @@ function stopProcess() {
sendStop
=
true
;
sendStop
=
true
;
var
urlfor
=
$SCRIPT_ROOT
+
"
stopSlapgrid
"
,
var
urlfor
=
$SCRIPT_ROOT
+
"
stopSlapgrid
"
,
type
=
"
slapgrid-sr
.pid
"
;
type
=
"
slapgrid-sr
"
;
if
(
$
(
"
#instrun
"
).
text
()
===
"
Stop
"
)
{
if
(
$
(
"
#instrun
"
).
text
()
===
"
Stop
"
)
{
type
=
"
slapgrid-cp
.pid
"
;
type
=
"
slapgrid-cp
"
;
}
}
$
.
post
(
urlfor
,
{
type
:
type
},
function
(
data
)
{
$
.
post
(
urlfor
,
{
type
:
type
},
function
(
data
)
{
//if (data.result) {
//if (data.result) {
...
...
slapos/runner/utils.py
View file @
f78c9d5c
...
@@ -7,10 +7,9 @@ import md5
...
@@ -7,10 +7,9 @@ import md5
import
logging
import
logging
import
multiprocessing
import
multiprocessing
import
re
import
re
import
signal
from
slapos.runner.process
import
Popen
,
isRunning
,
killRunningProcess
import
shutil
import
shutil
import
os
import
os
import
subprocess
import
time
import
time
import
urllib
import
urllib
from
xml.dom
import
minidom
from
xml.dom
import
minidom
...
@@ -20,22 +19,12 @@ from flask import jsonify
...
@@ -20,22 +19,12 @@ from flask import jsonify
import
slapos.slap
import
slapos.slap
# Setup default flask (werkzeug) parser
# Setup default flask (werkzeug) parser
logger
=
logging
.
getLogger
(
'werkzeug'
)
logger
=
logging
.
getLogger
(
'werkzeug'
)
class
Popen
(
subprocess
.
Popen
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
kwargs
[
'stdin'
]
=
subprocess
.
PIPE
kwargs
[
'stderr'
]
=
subprocess
.
STDOUT
kwargs
.
setdefault
(
'stdout'
,
subprocess
.
PIPE
)
kwargs
.
setdefault
(
'close_fds'
,
True
)
subprocess
.
Popen
.
__init__
(
self
,
*
args
,
**
kwargs
)
self
.
stdin
.
flush
()
self
.
stdin
.
close
()
self
.
stdin
=
None
html_escape_table
=
{
html_escape_table
=
{
"&"
:
"&"
,
"&"
:
"&"
,
'"'
:
"""
,
'"'
:
"""
,
...
@@ -177,54 +166,6 @@ def updateProxy(config):
...
@@ -177,54 +166,6 @@ def updateProxy(config):
computer
.
updateConfiguration
(
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_config
))
computer
.
updateConfiguration
(
xml_marshaller
.
xml_marshaller
.
dumps
(
slap_config
))
return
True
return
True
def
readPid
(
file
):
"""Read process pid from file `file`"""
if
os
.
path
.
exists
(
file
):
data
=
open
(
file
).
read
().
strip
()
try
:
return
int
(
data
)
except
Exception
:
return
0
return
0
def
writePid
(
file
,
pid
):
"""Save process pid into a file `file`"""
open
(
file
,
'w'
).
write
(
str
(
pid
))
def
killRunningProcess
(
config
,
ptype
):
"""Kill process and all running children process and remove pidfile"""
process_pid
=
os
.
path
.
join
(
config
[
'run_dir'
],
ptype
)
pid
=
readPid
(
process_pid
)
if
pid
:
recursifKill
([
pid
])
os
.
remove
(
process_pid
)
else
:
return
False
def
recursifKill
(
pids
):
"""Try to kill a list of proccess by the given pid list"""
if
pids
==
[]:
return
else
:
for
pid
in
pids
:
ppids
=
pidppid
(
pid
)
try
:
os
.
kill
(
pid
,
signal
.
SIGKILL
)
#kill current process
except
Exception
:
pass
recursifKill
(
ppids
)
#kill all children of this process
def
pidppid
(
pid
):
"""get the list of the children pids of a process `pid`"""
proc
=
Popen
(
'ps -o pid,ppid ax | grep "%d"'
%
pid
,
shell
=
True
,
stdout
=
subprocess
.
PIPE
)
ppid
=
[
x
.
split
()
for
x
in
proc
.
communicate
()[
0
].
split
(
"
\
n
"
)
if
x
]
return
list
(
int
(
p
)
for
p
,
pp
in
ppid
if
int
(
pp
)
==
pid
)
def
updateInstanceParameter
(
config
,
software_type
=
None
):
def
updateInstanceParameter
(
config
,
software_type
=
None
):
"""
"""
Reconfigure Slapproxy to re-deploy current Software Instance with parameters.
Reconfigure Slapproxy to re-deploy current Software Instance with parameters.
...
@@ -238,27 +179,17 @@ def updateInstanceParameter(config, software_type=None):
...
@@ -238,27 +179,17 @@ def updateInstanceParameter(config, software_type=None):
def
startProxy
(
config
):
def
startProxy
(
config
):
"""Start Slapproxy server"""
"""Start Slapproxy server"""
proxy_pid
=
os
.
path
.
join
(
config
[
'run_dir'
],
'proxy.pid'
)
if
not
isRunning
(
'slapproxy'
):
pid
=
readPid
(
proxy_pid
)
running
=
False
if
pid
:
try
:
os
.
kill
(
pid
,
0
)
except
Exception
:
pass
else
:
running
=
True
if
not
running
:
log
=
os
.
path
.
join
(
config
[
'log_dir'
],
'slapproxy.log'
)
log
=
os
.
path
.
join
(
config
[
'log_dir'
],
'slapproxy.log'
)
proxy
=
Popen
([
config
[
'slapproxy'
],
'--log_file'
,
log
,
Popen
([
config
[
'slapproxy'
],
'--log_file'
,
log
,
config
[
'configuration_file_path'
]])
config
[
'configuration_file_path'
]],
writePid
(
proxy_pid
,
proxy
.
pid
)
name
=
'slapproxy'
)
time
.
sleep
(
4
)
time
.
sleep
(
4
)
def
stopProxy
(
config
):
def
stopProxy
(
config
):
"""Stop Slapproxy server"""
"""Stop Slapproxy server"""
killRunningProcess
(
config
,
'proxy.pid'
)
pass
def
removeProxyDb
(
config
):
def
removeProxyDb
(
config
):
...
@@ -267,22 +198,11 @@ def removeProxyDb(config):
...
@@ -267,22 +198,11 @@ def removeProxyDb(config):
if
os
.
path
.
exists
(
config
[
'database_uri'
]):
if
os
.
path
.
exists
(
config
[
'database_uri'
]):
os
.
unlink
(
config
[
'database_uri'
])
os
.
unlink
(
config
[
'database_uri'
])
def
isSoftwareRunning
(
config
):
def
isSoftwareRunning
(
config
=
None
):
"""
"""
Return True if slapgrid-sr is still running and false if slapgrid if not
Return True if slapgrid-sr is still running and false if slapgrid if not
"""
"""
slapgrid_pid
=
os
.
path
.
join
(
config
[
'run_dir'
],
'slapgrid-sr.pid'
)
return
isRunning
(
'slapgrid-sr'
)
pid
=
readPid
(
slapgrid_pid
)
if
pid
:
try
:
os
.
kill
(
pid
,
0
)
except
Exception
:
running
=
False
else
:
running
=
True
else
:
running
=
False
return
running
def
runSoftwareWithLock
(
config
):
def
runSoftwareWithLock
(
config
):
...
@@ -291,7 +211,7 @@ def runSoftwareWithLock(config):
...
@@ -291,7 +211,7 @@ def runSoftwareWithLock(config):
compilation is done
compilation is done
"""
"""
slapgrid_pid
=
os
.
path
.
join
(
config
[
'run_dir'
],
'slapgrid-sr.pid'
)
slapgrid_pid
=
os
.
path
.
join
(
config
[
'run_dir'
],
'slapgrid-sr.pid'
)
if
not
isSoftwareRunning
(
config
):
if
not
isSoftwareRunning
():
if
not
os
.
path
.
exists
(
config
[
'software_root'
]):
if
not
os
.
path
.
exists
(
config
[
'software_root'
]):
os
.
mkdir
(
config
[
'software_root'
])
os
.
mkdir
(
config
[
'software_root'
])
stopProxy
(
config
)
stopProxy
(
config
)
...
@@ -304,9 +224,10 @@ def runSoftwareWithLock(config):
...
@@ -304,9 +224,10 @@ def runSoftwareWithLock(config):
environment
=
os
.
environ
.
copy
()
environment
=
os
.
environ
.
copy
()
environment
[
'MAKEFLAGS'
]
=
'-j%r'
%
multiprocessing
.
cpu_count
()
environment
[
'MAKEFLAGS'
]
=
'-j%r'
%
multiprocessing
.
cpu_count
()
slapgrid
=
Popen
([
config
[
'slapgrid_sr'
],
'-vc'
,
slapgrid
=
Popen
([
config
[
'slapgrid_sr'
],
'-vc'
,
'--pidfile'
,
slapgrid_pid
,
'--pidfile'
,
slapgrid_pid
,
config
[
'configuration_file_path'
],
'--now'
,
'--develop'
],
config
[
'configuration_file_path'
],
'--now'
,
'--develop'
],
stdout
=
logfile
,
env
=
environment
)
stdout
=
logfile
,
env
=
environment
,
name
=
'slapgrid-sr'
)
slapgrid
.
wait
()
slapgrid
.
wait
()
#Saves the current compile software for re-use
#Saves the current compile software for re-use
config_SR_folder
(
config
)
config_SR_folder
(
config
)
...
@@ -362,22 +283,11 @@ def loadSoftwareRList(config):
...
@@ -362,22 +283,11 @@ def loadSoftwareRList(config):
list
.
append
(
dict
(
md5
=
cfg
[
1
],
path
=
cfg
[
0
],
title
=
path
))
list
.
append
(
dict
(
md5
=
cfg
[
1
],
path
=
cfg
[
0
],
title
=
path
))
return
list
return
list
def
isInstanceRunning
(
config
):
def
isInstanceRunning
(
config
=
None
):
"""
"""
Return True if slapgrid-cp is still running and false if slapgrid if not
Return True if slapgrid-cp is still running and false if slapgrid if not
"""
"""
slapgrid_pid
=
os
.
path
.
join
(
config
[
'run_dir'
],
'slapgrid-cp.pid'
)
return
isRunning
(
'slapgrid-cp'
)
pid
=
readPid
(
slapgrid_pid
)
if
pid
:
try
:
os
.
kill
(
pid
,
0
)
except
Exception
:
running
=
False
else
:
running
=
True
else
:
running
=
False
return
running
def
runInstanceWithLock
(
config
):
def
runInstanceWithLock
(
config
):
...
@@ -386,16 +296,16 @@ def runInstanceWithLock(config):
...
@@ -386,16 +296,16 @@ def runInstanceWithLock(config):
deployment is done.
deployment is done.
"""
"""
slapgrid_pid
=
os
.
path
.
join
(
config
[
'run_dir'
],
'slapgrid-cp.pid'
)
slapgrid_pid
=
os
.
path
.
join
(
config
[
'run_dir'
],
'slapgrid-cp.pid'
)
if
not
isInstanceRunning
(
config
):
if
not
isInstanceRunning
():
startProxy
(
config
)
startProxy
(
config
)
logfile
=
open
(
config
[
'instance_log'
],
'w'
)
logfile
=
open
(
config
[
'instance_log'
],
'w'
)
if
not
(
updateProxy
(
config
)
and
requestInstance
(
config
)):
if
not
(
updateProxy
(
config
)
and
requestInstance
(
config
)):
return
False
return
False
svcStopAll
(
config
)
#prevent lost control of process
svcStopAll
(
config
)
#prevent lost control of process
slapgrid
=
Popen
([
config
[
'slapgrid_cp'
],
'-vc'
,
slapgrid
=
Popen
([
config
[
'slapgrid_cp'
],
'-vc'
,
'--pidfile'
,
slapgrid_pid
,
'--pidfile'
,
slapgrid_pid
,
config
[
'configuration_file_path'
],
'--now'
],
config
[
'configuration_file_path'
],
'--now'
],
stdout
=
logfile
)
stdout
=
logfile
,
name
=
'slapgrid-cp'
)
slapgrid
.
wait
()
slapgrid
.
wait
()
return
True
return
True
return
False
return
False
...
@@ -587,10 +497,10 @@ def configNewSR(config, projectpath):
...
@@ -587,10 +497,10 @@ def configNewSR(config, projectpath):
"""
"""
folder = realpath(config, projectpath)
folder = realpath(config, projectpath)
if folder:
if folder:
if isInstanceRunning(
config
):
if isInstanceRunning():
killRunningProcess(
config, "slapgrid-cp.pid"
)
killRunningProcess(
'
slapgrid
-
cp
'
)
if isSoftwareRunning(
config
):
if isSoftwareRunning():
killRunningProcess(
config, "slapgrid-sr.pid"
)
killRunningProcess(
'
slapgrid
-
sr
'
)
stopProxy(config)
stopProxy(config)
removeProxyDb(config)
removeProxyDb(config)
startProxy(config)
startProxy(config)
...
@@ -672,7 +582,7 @@ def removeSoftwareByName(config, md5, folderName):
...
@@ -672,7 +582,7 @@ def removeSoftwareByName(config, md5, folderName):
config: slaprunner configuration
config: slaprunner configuration
foldername: the link name given to the software release
foldername: the link name given to the software release
md5: the md5 filename given by slapgrid to SR folder"""
md5: the md5 filename given by slapgrid to SR folder"""
if isSoftwareRunning(
config) or isInstanceRunning(config
):
if isSoftwareRunning(
) or isInstanceRunning(
):
raise Exception("Software installation or instantiation in progress, cannot remove")
raise Exception("Software installation or instantiation in progress, cannot remove")
path = os.path.join(config['
software_root
'], md5)
path = os.path.join(config['
software_root
'], md5)
linkpath = os.path.join(config['
software_link
'], folderName)
linkpath = os.path.join(config['
software_link
'], folderName)
...
...
slapos/runner/views.py
View file @
f78c9d5c
...
@@ -11,9 +11,10 @@ from flaskext.auth import Auth, AuthUser, login_required, logout
...
@@ -11,9 +11,10 @@ from flaskext.auth import Auth, AuthUser, login_required, logout
from
flask
import
(
Flask
,
request
,
redirect
,
url_for
,
render_template
,
from
flask
import
(
Flask
,
request
,
redirect
,
url_for
,
render_template
,
g
,
flash
,
jsonify
,
session
,
abort
,
send_file
)
g
,
flash
,
jsonify
,
session
,
abort
,
send_file
)
from
slapos.runner.process
import
killRunningProcess
from
slapos.runner.utils
import
(
checkSoftwareFolder
,
configNewSR
,
getFolder
,
getFolderContent
,
getProfilePath
,
from
slapos.runner.utils
import
(
checkSoftwareFolder
,
configNewSR
,
getFolder
,
getFolderContent
,
getProfilePath
,
getProjectList
,
getProjectTitle
,
getSession
,
getSlapStatus
,
getSvcStatus
,
getProjectList
,
getProjectTitle
,
getSession
,
getSlapStatus
,
getSvcStatus
,
getSvcTailProcess
,
isInstanceRunning
,
isSoftwareRunning
,
isText
,
killRunningProcess
,
getSvcTailProcess
,
isInstanceRunning
,
isSoftwareRunning
,
isText
,
loadSoftwareRList
,
md5sum
,
newSoftware
,
readFileFrom
,
readParameters
,
realpath
,
loadSoftwareRList
,
md5sum
,
newSoftware
,
readFileFrom
,
readParameters
,
realpath
,
removeInstanceRoot
,
removeProxyDb
,
removeSoftwareByName
,
runInstanceWithLock
,
removeInstanceRoot
,
removeProxyDb
,
removeSoftwareByName
,
runInstanceWithLock
,
runSoftwareWithLock
,
saveSession
,
svcStartStopProcess
,
svcStopAll
,
tail
,
runSoftwareWithLock
,
saveSession
,
svcStartStopProcess
,
svcStopAll
,
tail
,
...
@@ -427,7 +428,7 @@ def slapgridResult():
...
@@ -427,7 +428,7 @@ def slapgridResult():
@
login_required
()
@
login_required
()
def
stopSlapgrid
():
def
stopSlapgrid
():
result
=
killRunningProcess
(
app
.
config
,
request
.
form
[
'type'
])
result
=
killRunningProcess
(
request
.
form
[
'type'
])
return
jsonify
(
result
=
result
)
return
jsonify
(
result
=
result
)
@
login_required
()
@
login_required
()
...
...
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