mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 611348 - adding functionality to devicemanager.py to handle slave rebooting r=jmaher a=NPOTB
This commit is contained in:
parent
a792acda7d
commit
663acccd84
@ -37,6 +37,7 @@
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import socket
|
||||
import SocketServer
|
||||
import time, datetime
|
||||
import os
|
||||
import re
|
||||
@ -58,14 +59,14 @@ class FileError(Exception):
|
||||
class DeviceManager:
|
||||
host = ''
|
||||
port = 0
|
||||
debug = 2
|
||||
debug = 2
|
||||
_redo = False
|
||||
deviceRoot = None
|
||||
tempRoot = os.getcwd()
|
||||
base_prompt = '\$\>'
|
||||
prompt_sep = '\x00'
|
||||
prompt_regex = '.*' + base_prompt + prompt_sep
|
||||
agentErrorRE = re.compile('^##AGENT-ERROR##.*')
|
||||
agentErrorRE = re.compile('^##AGENT-WARNING##.*')
|
||||
|
||||
def __init__(self, host, port = 20701):
|
||||
self.host = host
|
||||
@ -272,7 +273,10 @@ class DeviceManager:
|
||||
return None
|
||||
|
||||
def mkDir(self, name):
|
||||
return self.sendCMD(['mkdr ' + name])
|
||||
if (self.dirExists(name)):
|
||||
return name
|
||||
else:
|
||||
return self.sendCMD(['mkdr ' + name])
|
||||
|
||||
# make directory structure on the device
|
||||
def mkDirs(self, filename):
|
||||
@ -306,7 +310,9 @@ class DeviceManager:
|
||||
match = ".*" + dirname + "$"
|
||||
dirre = re.compile(match)
|
||||
data = self.sendCMD(['cd ' + dirname, 'cwd'])
|
||||
if (data == None):
|
||||
# Because this is a compound command, cd can fail while cwd can succeed,
|
||||
# we should check for agent error directly
|
||||
if (data == None or self.agentErrorRE.match(data) ):
|
||||
return None
|
||||
retVal = self.stripPrompt(data)
|
||||
data = retVal.split('\n')
|
||||
@ -549,11 +555,12 @@ class DeviceManager:
|
||||
# /reftest
|
||||
# /mochitest
|
||||
def getDeviceRoot(self):
|
||||
if (not self.deviceRoot):
|
||||
data = self.sendCMD(['testroot'])
|
||||
if (data == None):
|
||||
return '/tests'
|
||||
self.deviceRoot = self.stripPrompt(data).strip('\n') + '/tests'
|
||||
# This caching of deviceRoot is causing issues if things fail
|
||||
# if (not self.deviceRoot):
|
||||
data = self.sendCMD(['testroot'])
|
||||
if (data == None):
|
||||
return '/tests'
|
||||
self.deviceRoot = self.stripPrompt(data).strip('\n') + '/tests'
|
||||
|
||||
if (not self.dirExists(self.deviceRoot)):
|
||||
self.mkDir(self.deviceRoot)
|
||||
@ -690,8 +697,8 @@ class DeviceManager:
|
||||
Application bundle - path to the application bundle on the device
|
||||
Destination - destination directory of where application should be
|
||||
installed to (optional)
|
||||
Returns True or False depending on what we get back
|
||||
TODO: we need a real way to know if this works or not
|
||||
Returns None for success, or output if known failure
|
||||
TODO: we need a better way to know if this works or not
|
||||
"""
|
||||
def installApp(self, appBundlePath, destPath=None):
|
||||
cmd = 'inst ' + appBundlePath
|
||||
@ -699,9 +706,13 @@ class DeviceManager:
|
||||
cmd += ' ' + destPath
|
||||
data = self.sendCMD([cmd])
|
||||
if (data is None):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
return None
|
||||
|
||||
f = re.compile('Failure')
|
||||
for line in data.split():
|
||||
if (f.match(line)):
|
||||
return data
|
||||
return None
|
||||
|
||||
"""
|
||||
Uninstalls the named application from device and causes a reboot.
|
||||
@ -714,9 +725,53 @@ class DeviceManager:
|
||||
cmd = 'uninst ' + appName
|
||||
if installPath:
|
||||
cmd += ' ' + installPath
|
||||
self.sendCMD([cmd])
|
||||
data = self.sendCMD([cmd])
|
||||
if (self.debug > 3): print "uninstallAppAndReboot: " + str(data)
|
||||
return True
|
||||
|
||||
"""
|
||||
Updates the application on the device.
|
||||
Application bundle - path to the application bundle on the device
|
||||
Process name of application - used to end the process if the applicaiton is
|
||||
currently running
|
||||
Destination - Destination directory to where the application should be
|
||||
installed (optional)
|
||||
ipAddr - IP address to await a callback ping to let us know that the device has updated
|
||||
properly - defaults to current IP.
|
||||
port - port to await a callback ping to let us know that the device has updated properly
|
||||
defaults to 30000, and counts up from there if it finds a conflict
|
||||
Returns True if succeeds, False if not
|
||||
|
||||
NOTE: We have no real way to know if the device gets updated or not due to the
|
||||
reboot that the udpate call forces on us. We can't install our own heartbeat
|
||||
listener here because we run the risk of racing with other heartbeat listeners.
|
||||
"""
|
||||
def updateApp(self, appBundlePath, processName=None, destPath=None, ipAddr=None, port=None):
|
||||
status = None
|
||||
cmd = 'updt '
|
||||
if (processName == None):
|
||||
# Then we pass '' for processName
|
||||
cmd += "'' " + appBundlePath
|
||||
else:
|
||||
cmd += processName + ' ' + appBundlePath
|
||||
|
||||
if (destPath):
|
||||
cmd += " " + destPath
|
||||
|
||||
ip, port = self.getCallbackIpAndPort(ipAddr, 30000)
|
||||
|
||||
cmd += " %s %s" % (ip, port)
|
||||
|
||||
if (self.debug > 3): print "updateApp using command: " + str(cmd)
|
||||
|
||||
# Set up our callback server
|
||||
callbacksvr = callbackServer(ip, port, self.debug)
|
||||
data = self.sendCMD([cmd])
|
||||
status = callbacksvr.disconnect()
|
||||
if (self.debug > 3): print "got status back: " + str(status)
|
||||
|
||||
return status
|
||||
|
||||
"""
|
||||
return the current time on the device
|
||||
"""
|
||||
@ -726,3 +781,112 @@ class DeviceManager:
|
||||
return None
|
||||
return self.stripPrompt(data).strip('\n')
|
||||
|
||||
"""
|
||||
Connect the ipaddress and port for a callback ping. Defaults to current IP address
|
||||
And ports starting at 30000.
|
||||
NOTE: the detection for current IP address only works on Linux!
|
||||
"""
|
||||
def getCallbackIpAndPort(self, aIp, aPort):
|
||||
ip = aIp
|
||||
nettools = NetworkTools()
|
||||
if (ip == None):
|
||||
ip = nettools.getLanIp()
|
||||
if (aPort != None):
|
||||
port = nettools.findOpenPort(ip, aPort)
|
||||
else:
|
||||
port = nettools.findOpenPort(ip, 30000)
|
||||
return ip, port
|
||||
|
||||
gCallbackData = ''
|
||||
|
||||
class callbackServer():
|
||||
def __init__(self, ip, port, debuglevel):
|
||||
self.ip = ip
|
||||
self.port = port
|
||||
self.connected = False
|
||||
self.debug = debuglevel
|
||||
if (self.debug > 3) : print "Creating server with " + str(ip) + ":" + str(port)
|
||||
self.server = SocketServer.TCPServer((ip, port), self.myhandler)
|
||||
self.server_thread = Thread(target=self.server.serve_forever)
|
||||
self.server_thread.setDaemon(True)
|
||||
self.server_thread.start()
|
||||
|
||||
def disconnect(self, step = 60, timeout = 600):
|
||||
t = 0
|
||||
if (self.debug > 3): print "Calling disconnect on callback server"
|
||||
while t < timeout:
|
||||
if (gCallbackData):
|
||||
# Got the data back
|
||||
if (self.debug > 3): print "Got data back from agent: " + str(gCallbackData)
|
||||
break
|
||||
time.sleep(step)
|
||||
t += step
|
||||
|
||||
try:
|
||||
if (self.debug > 3): print "Shutting down server now"
|
||||
self.server.shutdown()
|
||||
except:
|
||||
print "Unable to shutdown callback server - check for a connection on port: " + str(self.port)
|
||||
return gCallbackData
|
||||
|
||||
class myhandler(SocketServer.BaseRequestHandler):
|
||||
def handle(self):
|
||||
global gCallbackData
|
||||
gCallbackData = self.request.recv(1024)
|
||||
#print "Callback Handler got data: " + str(gCallbackData)
|
||||
self.request.send("OK")
|
||||
|
||||
class NetworkTools:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
# Utilities to get the local ip address
|
||||
def getInterfaceIp(self, ifname):
|
||||
if os.name != "nt":
|
||||
import fcntl
|
||||
import struct
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
return socket.inet_ntoa(fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8915, # SIOCGIFADDR
|
||||
struct.pack('256s', ifname[:15])
|
||||
)[20:24])
|
||||
else:
|
||||
return None
|
||||
|
||||
def getLanIp(self):
|
||||
ip = socket.gethostbyname(socket.gethostname())
|
||||
if ip.startswith("127.") and os.name != "nt":
|
||||
interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
|
||||
for ifname in interfaces:
|
||||
try:
|
||||
ip = self.getInterfaceIp(ifname)
|
||||
break;
|
||||
except IOError:
|
||||
pass
|
||||
return ip
|
||||
|
||||
# Gets an open port starting with the seed by incrementing by 1 each time
|
||||
def findOpenPort(self, ip, seed):
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
connected = False
|
||||
if isinstance(seed, basestring):
|
||||
seed = int(seed)
|
||||
maxportnum = seed + 5000 # We will try at most 5000 ports to find an open one
|
||||
while not connected:
|
||||
try:
|
||||
s.bind((ip, seed))
|
||||
connected = True
|
||||
s.close()
|
||||
except:
|
||||
if seed > maxportnum:
|
||||
print "Could not find open port after checking 5000 ports"
|
||||
raise
|
||||
seed += 1
|
||||
except:
|
||||
print "Socket error trying to find open port"
|
||||
|
||||
return seed
|
||||
|
||||
|
@ -42,7 +42,7 @@ import os
|
||||
import socket
|
||||
|
||||
from automation import Automation
|
||||
from devicemanager import DeviceManager
|
||||
from devicemanager import DeviceManager, NetworkTools
|
||||
|
||||
class RemoteAutomation(Automation):
|
||||
_devicemanager = None
|
||||
@ -99,31 +99,9 @@ class RemoteAutomation(Automation):
|
||||
# return app, ['--environ:NO_EM_RESTART=1'] + args
|
||||
return app, args
|
||||
|
||||
# Utilities to get the local ip address
|
||||
def getInterfaceIp(self, ifname):
|
||||
if os.name != "nt":
|
||||
import fcntl
|
||||
import struct
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
return socket.inet_ntoa(fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8915, # SIOCGIFADDR
|
||||
struct.pack('256s', ifname[:15])
|
||||
)[20:24])
|
||||
else:
|
||||
return None
|
||||
|
||||
def getLanIp(self):
|
||||
ip = socket.gethostbyname(socket.gethostname())
|
||||
if ip.startswith("127.") and os.name != "nt":
|
||||
interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
|
||||
for ifname in interfaces:
|
||||
try:
|
||||
ip = self.getInterfaceIp(ifname)
|
||||
break;
|
||||
except IOError:
|
||||
pass
|
||||
return ip
|
||||
nettools = NetworkTools()
|
||||
return nettools.getLanIp()
|
||||
|
||||
def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
|
||||
if stdout == None or stdout == -1:
|
||||
@ -176,4 +154,3 @@ class RemoteAutomation(Automation):
|
||||
|
||||
def kill(self):
|
||||
self.dm.killProcess(self.procName)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user