You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

365 lines
11 KiB
Python

import os, os.path, glob
import subprocess
import commands
import time
import sys
import re
from subprocess import Popen
from os.path import basename
DEV_NULL = file("/dev/null","w")
DAEMONS_TO_BE_STOPPED = ['xsession/applifed','xsession/conndlgs']
LAUNCHER_BINARY='/usr/bin/applauncherd'
DEV_NULL = file("/dev/null","w")
LAUNCHABLE_APPS = ['/usr/bin/fala_ft_hello','/usr/bin/fala_ft_hello1', '/usr/bin/fala_ft_hello2']
LAUNCHABLE_APPS_QML = ['/usr/bin/fala_qml_helloworld','/usr/bin/fala_qml_helloworld1', '/usr/bin/fala_qml_helloworld2']
PREFERED_APP = '/usr/bin/fala_ft_hello'
PREFERED_APP_QML = '/usr/bin/fala_qml_helloworld'
GET_COORDINATE_SCRIPT = '/usr/share/applauncherd-testscripts/get-coordinates.rb'
PIXELCHANHED_BINARY = '/usr/bin/fala_pixelchanged'
# Function to stop desired daemons. This is also done in setup function
# if stop_daemons is not called before.
def stop_daemons():
for daemon in DAEMONS_TO_BE_STOPPED:
os.system('initctl stop %s'%(daemon))
wait_for_single_applauncherd()
get_booster_pid()
# Function to start desired daemons. This is also done in teardown function
# if start_daemons is not called before.
def start_daemons():
for daemon in DAEMONS_TO_BE_STOPPED:
os.system('initctl start %s'%(daemon))
wait_for_single_applauncherd()
get_booster_pid()
def daemons_running():
st, op = commands.getstatusoutput('pgrep %s'%DAEMONS_TO_BE_STOPPED[0].split("/")[1])
return not(st)
def debug(*msg):
"""
Debug function
"""
sys.stderr.write('[DEBUG %s] %s\n' % (time.ctime(), \
' '.join([str(s) for s in msg]),))
def error(*msg):
"""
exit when error, give proper log
"""
sys.stderr.write('ERROR %s\n' % (' '.join([str(s) for s in msg]),))
sys.exit(1)
def remove_applauncherd_runtime_files():
"""
Removes files that applauncherd leaves behind after it has been stopped
"""
debug("Removing files that applauncherd leaves behind after it has been stopped")
files = glob.glob('/tmp/boost*')
for f in files:
debug("removing %s" % f)
try:
os.remove(f)
except:
pass
def start_applauncherd():
debug("Starting applauncherd")
handle = Popen(['initctl', 'start', 'xsession/applauncherd'],
stdout = DEV_NULL, stderr = DEV_NULL,
shell = False)
get_booster_pid()
return handle.wait() == 0
def stop_applauncherd():
debug("Stoping applauncherd")
handle = Popen(['initctl', 'stop', 'xsession/applauncherd'],
stdout = DEV_NULL, stderr = DEV_NULL,
shell = False)
time.sleep(1)
remove_applauncherd_runtime_files()
return handle.wait()
def restart_applauncherd():
debug("Restart applauncherd")
stop_applauncherd()
start_applauncherd()
def run_app_as_user_with_invoker(appname, booster = 'm', arg = "", out = DEV_NULL, err = DEV_NULL):
"""
Runs the specified app as a user.
"""
inv_cmd = "/usr/bin/invoker --type=%s %s %s" %(booster,arg, appname)
debug("run %s as user" %inv_cmd)
cmd = ['su', '-', 'user', '-c']
if type(appname) == list:
cmd += inv_cmd
elif type(appname) == str:
cmd.append(inv_cmd)
else:
raise TypeError("List or string expected")
p = subprocess.Popen(cmd, shell = False,
stdout = out, stderr = err)
return p
def run_cmd_as_user(cmnd, out = DEV_NULL, err = DEV_NULL):
"""
Runs the specified command as a user.
"""
debug("run %s as user" %cmnd)
cmd = ['su', '-', 'user', '-c']
if type(cmnd) == list:
cmd += cmnd
elif type(cmnd) == str:
cmd.append(cmnd)
else:
raise TypeError("List or string expected")
p = subprocess.Popen(cmd, shell = False,
stdout = out, stderr = err)
return p
def get_pid(appname):
temp = basename(appname)[:14]
st, op = commands.getstatusoutput("pgrep %s" % temp)
debug("The Pid of %s is %s" %(appname, op))
if st == 0:
return op
else:
return None
def get_oldest_pid(appname):
temp = basename(appname)[:14]
st, op = commands.getstatusoutput("pgrep -o %s" % temp)
debug("The Pid of %s is %s" %(appname, op))
if st == 0:
return op
else:
return None
def get_newest_pid(app):
p = subprocess.Popen(['pgrep', '-n', app], shell = False,
stdout = subprocess.PIPE, stderr = DEV_NULL)
op = p.communicate()[0]
debug("The New Pid of %s is %s" %(app, op.strip()))
if p.wait() == 0:
return op.strip()
return None
def wait_for_app(app = None, timeout = 40, sleep = 1):
"""
Waits for an application to start. Checks periodically if
the app is running for a maximum wait set in timeout.
Returns the pid of the application if it was running before
the timeout finished, otherwise None is returned.
"""
pid = None
start = time.time()
while pid == None and time.time() < start + timeout:
pid = get_newest_pid(app)
if pid != None:
break
debug("waiting %s secs for %s" % (sleep, app))
time.sleep(sleep)
return pid
def wait_for_single_applauncherd(timeout = 20, sleep = 1):
pid = get_pid('applauncherd')
count = len(pid.split("\n"))
start = time.time()
while count > 1 and time.time() < start + timeout:
debug("waiting %s secs for single applauncherd" %sleep)
time.sleep(sleep)
pid = get_pid('applauncherd')
count = len(pid.split("\n"))
if count == 1:
break
return pid
def get_booster_pid():
qpid = wait_for_app('booster-q')
epid = wait_for_app('booster-e')
dpid = wait_for_app('booster-d')
mpid = wait_for_app('booster-m')
return (epid, dpid, qpid, mpid)
def kill_process(appname=None, apppid=None, signum=15):
# obtained by running 'kill -l'
signal = {1: "HUP", 2: "INT", 3: "QUIT", 4: "ILL", 5: "TRAP", 6: "ABRT", 7: "BUS",
8: "FPE", 9: "KILL", 10: "USR1", 11: "SEGV", 12: "USR2", 13: "PIPE",
14: "ALRM", 15: "TERM", 16: "STKFLT", 17: "CHLD", 18: "CONT", 19: "STOP",
20: "TSTP", 21: "TTIN", 22: "TTOU", 23: "URG", 24: "XCPU", 25: "XFSZ",
26: "VTALRM", 27: "PROF", 28: "WINCH", 29: "POLL", 30: "PWR", 31: "SYS"}
if signal.has_key(signum):
signame = "SIG%s" % signal[signum]
else:
# should never reach this
signame = "signal %s" % signum
if apppid and appname:
return None
else:
if apppid:
debug("Now sending %s to the app with pid %s" % (signame, apppid))
st, op = commands.getstatusoutput("kill -%s %s" % (str(signum), str(apppid)))
if appname:
debug("Now sending %s to %s" % (signame, appname))
temp = basename(appname)[:14]
st, op = commands.getstatusoutput("pkill -%s %s" % (str(signum), temp))
def process_state(processid):
st, op = commands.getstatusoutput('cat /proc/%s/stat' %processid)
debug("The Process State of %s is %s" %(processid, op))
if st == 0:
return op
else:
debug(op)
return None
def get_creds(path = None, pid = None):
"""
Tries to retrieve credentials for a running application
using either the pid or path. Credentials are returned
as a string list.
"""
if path != None:
pid = get_pid(path)
if pid == None:
print 'invalid PID'
return None
handle = Popen(['/usr/bin/creds-get', '-p', str(pid)],
stdout = subprocess.PIPE)
op = handle.communicate()[0].strip()
handle.wait()
if handle.returncode != 0:
print 'error retrieving credentials'
return None
#self.assert_(handle.returncode == 0, "There was no such PID!")
debug("creds-get gave >>>>>\n%s\n<<<<<" % op)
creds = op.split("\n")[1:]
return creds
def launch_and_get_creds(path):
"""
Tries to launch an application and if successful, returns the
credentials the application has as a list.
"""
# try launch the specified application
handle = run_app_as_user_with_invoker(path,arg = '--no-wait')
# sleep for a moment to allow applauncherd to start the process
time.sleep(3)
# with luck, the process should have correct name by now
pid = get_pid(path)
debug("%s has PID %s" % (basename(path), pid,))
if pid == None:
print "couldn't launch %s" % basename(path)
return None
creds = get_creds(pid = pid)
kill_process(path)
return creds
def get_file_descriptor(booster, type, app_name):
"""
To test that file descriptors are closed before calling application main
"""
#get fd of booster before launching application
debug("get fd of booster before launching application")
pid = commands.getoutput("pgrep '%s$'" %booster)
fd_info = commands.getoutput('ls -l /proc/%s/fd/' % str(pid))
fd_info = fd_info.split('\n')
init = {}
final = {}
for fd in fd_info:
if "->" in fd:
init[fd.split(" -> ")[0].split(' ')[-1]] = fd.split(" -> ")[-1]
debug("\nThe initial file descriptors are : %s\n" %init)
#launch application using booster
debug("launch %s using booster" % app_name)
st = os.system('invoker --type=%s --no-wait /usr/bin/%s' % (type, app_name))
time.sleep(4)
#get fd of booster after launching the application
debug("get fd of booster after launching the application")
if st == 0:
fd_info = commands.getoutput('ls -l /proc/%s/fd/' % str(pid))
fd_info = fd_info.split('\n')
for fd in fd_info:
if "->" in fd:
final[fd.split(" -> ")[0].split(' ')[-1]] = fd.split(" -> ")[-1]
debug("\nThe final file descriptors are : %s\n" %final)
pid = commands.getoutput('pgrep %s' % app_name)
mykeys = init.keys()
count = 0
for key in mykeys:
try:
if init[key] != final[key]:
count = count + 1
except KeyError:
print "some key in init is not in final"
time.sleep(4)
debug("The number of changed file descriptors %d" %count)
kill_process(apppid=pid)
return count
def get_groups_for_user():
# get supplementary groups user belongs to (doesn't return
# the gid group)
p = run_cmd_as_user('id -Gn', out = subprocess.PIPE)
groups = p.communicate()[0].split()
debug("The groups for users is :%s" %groups)
p.wait()
return groups
def send_sighup_to_applauncherd():
pid1 = get_oldest_pid('applauncherd')
(e1, d1, q1, m1) = get_booster_pid()
debug("before sighup, applauncherd pid = ", pid1)
kill_process(None, pid1, 1)
time.sleep(5)
pid2 = wait_for_single_applauncherd()
(e2, d2, q2, m2) = get_booster_pid()
debug("after sighup, applauncherd pid = ", pid2)
return (pid1==pid2, m1!=m2 and q1!=q2 and d1!=d2 and e1!=e2)