Skip to content
Snippets Groups Projects
Commit 35959f46 authored by Jonathan Ehret's avatar Jonathan Ehret
Browse files

refactor launcher script and change configs to json format

parent 6ea6a8aa
No related branches found
No related tags found
No related merge requests found
{
"sLocalIP": "10.0.1.240",
"nLocalPort": 41578,
"nDefaultSleep": 5,
"tVirtualAcousticVersions" = {
"20160906.aixcave" : { "file": "bin/VAServer.exe", "dir": "D:/Demos/VA_20160906/Binaries", "params": "10.0.1.240:12340 conf/VACore.aixcave.ini" },
"20160906.aixcave.barrend" : { "file": "bin/VAServer.exe", "dir": "D:/Demos/VA_20160906/Binaries", "params": "10.0.1.240:12340 conf/VACore.aixcave.barrend.ini" },
"20161206.aixcave" : { "file": "bin/VAServer.exe", "dir": "D:/Demos/VA_20161206", "params": "10.0.1.240:12340 conf/VACore.aixcave.ini" },
"20161206.aixcave.barrend" : { "file": "bin/VAServer.exe", "dir": "D:/Demos/VA_20161206", "params": "10.0.1.240:12340 conf/VACore.aixcave.barrend.ini" },
"2018.a" : { "file": "bin/VAServer.exe", "dir": "D:/VAServer-git/v2018.a", "params": "10.0.1.240:12340 conf/VACore.aixCAVE.ini" },
"2019.a" : { "file": "bin/VAServer.exe", "dir": "D:/VAServer-git/v2019.a_dev", "params": "10.0.1.240:12340 conf/VACore.aixCAVE.ini" },
"2020.a" : { "file": "bin/VAServer.exe", "dir": "D:/VAServer-git/v2020.a", "params": "10.0.1.240:12340 conf/VACore.aixCAVE.ini" },
"2020.a_AirTraffic" : { "file": "bin/VAServer.exe", "dir": "D:/VAServer-git/v2020.a", "params": "10.0.1.240:12340 conf/VACore.aixCAVE.ATNRenderer.ini" }
}
}
sLocalIP = "10.0.1.240"
nLocalPort = 41578
nDefaultSleep = 5
tVirtualAcousticVersions = {
"20160906.aixcave" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/Demos/VA_20160906/Binaries', "params" : '10.0.1.240:12340 conf/VACore.aixcave.ini' },
"20160906.aixcave.barrend" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/Demos/VA_20160906/Binaries', "params" : '10.0.1.240:12340 conf/VACore.aixcave.barrend.ini' },
"20161206.aixcave" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/Demos/VA_20161206', "params" : '10.0.1.240:12340 conf/VACore.aixcave.ini' },
"20161206.aixcave.barrend" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/Demos/VA_20161206', "params" : '10.0.1.240:12340 conf/VACore.aixcave.barrend.ini' },
"2018.a" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/VAServer-git/v2018.a', "params" : '10.0.1.240:12340 conf/VACore.aixCAVE.ini' },
"2019.a" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/VAServer-git/v2019.a_dev', "params" : '10.0.1.240:12340 conf/VACore.aixCAVE.ini' },
"2020.a" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/VAServer-git/v2020.a', "params" : '10.0.1.240:12340 conf/VACore.aixCAVE.ini' },
"2020.a_AirTraffic" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/VAServer-git/v2020.a', "params" : '10.0.1.240:12340 conf/VACore.aixCAVE.ATNRenderer.ini' }
}
{
"sLocalIP": "0.0.0.0",
"nLocalPort": 41578,
"nDefaultSleep": 3,
"tVirtualAcousticVersions": {
"2018.a": { "file": "bin/VAServer.exe", "dir": "../v2018.a", "params": "localhost:12340 conf/VACore.ini" },
"2019.a": { "file": "bin/VAServer.exe", "dir": "../v2019.a", "params": "localhost:12340 conf/VACore.ini" },
"2020.a": { "file": "bin/VAServer.exe", "dir": "../v2020.a", "params": "localhost:12340 conf/VACore.ini" },
"2020.a_AirTraffic": { "file": "bin/VAServer.exe", "dir": "../v2020.a", "params": "localhost:12340 conf/VACore.ATNRenderer.ini" }
}
}
sLocalIP = "0.0.0.0"
nLocalPort = 41578
nDefaultSleep = 3
tVirtualAcousticVersions = {
"2018.a" : { "file" : 'bin/VAServer.exe', "dir" : '../v2018.a', "params" : 'localhost:12340 conf\VACore.ini' },
"2019.a" : { "file" : 'bin/VAServer.exe', "dir" : '../v2019.a', "params" : 'localhost:12340 conf\VACore.ini' },
"2020.a" : { "file" : 'bin/VAServer.exe', "dir" : '../v2020.a', "params" : 'localhost:12340 conf\VACore.ini' },
"2020.a_AirTraffic" : { "file" : 'bin/VAServer.exe', "dir" : '../v2020.a', "params" : 'localhost:12340 conf\VACore.ATNRenderer.ini' }
}
import sys, socket, subprocess, time, os import sys, socket, subprocess, time, os, json
from enum import Enum
oProcess = None
class ErrorCodes(Enum):
NO_ERROR = 0
ERROR_NO_CONFIG_FOUND = 1
ERROR_INCOMPLETE_CONFIG = 2
ERROR_BINDING_SOCKET = 3
ERROR_CONNECTING_SOCKET = 4
class VirtualAcousticsLauncher:
def __init__(self):
print("init")
self.oVAProcess = None
self.oLauncherServerSocket = None
self.oLauncherConnection = None
self.sCurrentScriptsDirectory = os.path.dirname( os.path.realpath( sys.argv[0] ) )
self.start()
def start(self):
print( "VirtualAcoustics Starter script - press ctrl+c to quit" ) print( "VirtualAcoustics Starter script - press ctrl+c to quit" )
self.readConfig()
self.openLauncherServerSocket()
self.runLauncher()
sHostConfigurationFile = "VirtualAcousticStarterConfig." + socket.gethostname() + ".py" def readConfig(self):
sGeneralConfigurationFile = "VirtualAcousticStarterConfig.py" sHostConfigurationFile = "VirtualAcousticStarterConfig." + socket.gethostname() + ".json"
sCurrentScriptsDirectory = os.path.dirname( os.path.realpath( sys.argv[0] ) ) sGeneralConfigurationFile = "VirtualAcousticStarterConfig.json"
sUsedConfigFile = ""
#check which config file exists and load it
if os.path.isfile( sHostConfigurationFile ): if os.path.isfile( sHostConfigurationFile ):
exec( compile( open( sHostConfigurationFile, "rb" ).read(), sHostConfigurationFile, 'exec' ) ) sUsedConfigFile = sHostConfigurationFile
print("Using config: " + sHostConfigurationFile) elif os.path.isfile( self.sCurrentScriptsDirectory + "/" + sHostConfigurationFile ):
elif os.path.isfile( sCurrentScriptsDirectory + "/" + sHostConfigurationFile ): sUsedConfigFile = self.sCurrentScriptsDirectory + "/" + sHostConfigurationFile
exec( compile( open( sCurrentScriptsDirectory + "/" + sHostConfigurationFile, "rb" ).read(), sCurrentScriptsDirectory + "/" + sHostConfigurationFile, 'exec' ) )
print("Using config: " + sCurrentScriptsDirectory + "/" + sHostConfigurationFile)
elif os.path.isfile( sGeneralConfigurationFile ): elif os.path.isfile( sGeneralConfigurationFile ):
exec( compile( open( sGeneralConfigurationFile, "rb" ).read(), sGeneralConfigurationFile, 'exec' ) ) sUsedConfigFile = sGeneralConfigurationFile
print("Using config: " + sGeneralConfigurationFile) elif os.path.isfile( self.sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile ):
elif os.path.isfile( sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile ): sUsedConfigFile = self.sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile
exec( compile( open( sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile, "rb" ).read(), sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile, 'exec' ) )
print("Using config: " + sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile)
else: else:
print( "ERROR: No configuration file found - please create " + sHostConfigurationFile + " or " + sGeneralConfigurationFile ) print( "ERROR: No configuration file found - please create " + sHostConfigurationFile + " or " + sGeneralConfigurationFile )
sys.exit( 4 ) sys.exit( ErrorCodes.ERROR_NO_CONFIG_FOUND )
print("Using config: " + sUsedConfigFile)
with open( sUsedConfigFile) as json_file:
json_config = json.load(json_file)
try: try:
tVirtualAcousticVersions self.tVirtualAcousticVersions = json_config["tVirtualAcousticVersions"]
sLocalIP self.sLocalIP = json_config["sLocalIP"]
nLocalPort self.nLocalPort = json_config["nLocalPort"]
nDefaultSleep self.nDefaultSleep = json_config["nDefaultSleep"]
except NameError: except KeyError as e:
print( "ERROR: configuration did not define required variables: tVirtualAcousticVersions, sLocalIP, nLocalPort, nDefaultSleep" ) print( "ERROR reading the json config. Missing " + str(e.args[0]) )
sys.exit( 5 ) sys.exit( ErrorCodes.ERROR_INCOMPLETE_CONFIG )
print( "Creating server socket at " + sLocalIP + ":" + str( nLocalPort ) )
def openLauncherServerSocket(self):
oServer = socket.socket() print( "Creating server socket at " + self.sLocalIP + ":" + str( self.nLocalPort ) )
if sLocalIP == "":
sLocalIP = socket.gethostname() self.oLauncherServerSocket = socket.socket()
if self.sLocalIP == "":
self.sLocalIP = socket.gethostname()
try: try:
oServer.bind( ( sLocalIP, nLocalPort ) ) self.oLauncherServerSocket.bind( ( self.sLocalIP, self.nLocalPort ) )
oServer.listen( 3 ) self.oLauncherServerSocket.listen( 3 )
except socket.error: except socket.error:
print( "Error on binding socket" ) print( "Error on binding socket" )
sys.exit( 1 ) sys.exit( ErrorCodes.ERROR_BINDING_SOCKET )
self.oLauncherServerSocket.settimeout( 1.0 )
try:
oServer.settimeout( 0.5 ) def runLauncher(self):
try:
while True: while True:
print( "Waiting for connection..." ) print( "Waiting for launcher connection..." )
oConnection = None
while not oConnection: self.oLauncherConnection = None
while not self.oLauncherConnection:
try: try:
oConnection, sAddress = oServer.accept() self.oLauncherConnection, sAddress = self.oLauncherServerSocket.accept()
except socket.timeout: except socket.timeout:
oConnection = None self.oLauncherConnection = None
except socket.error: except socket.error:
print( "Error while listening for connection" ) print( "Error while listening for launcher connection" )
sys.exit( 2 ) sys.exit( ErrorCodes.ERROR_CONNECTING_SOCKET )
except (KeyboardInterrupt, SystemExit): except (KeyboardInterrupt, SystemExit):
raise raise #re-raising the received exception
print( "Connection received from " + sAddress[0] ) print( "Connection received from " + sAddress[0] )
if oProcess: if self.oVAProcess:
print( "Closing current VA instance" ) print( "Closing current VA instance" )
oProcess.kill() self.oVAProcess.kill()
oProcess = None self.oVAProcess = None
tInstanceToStart = self.ReadVariantToStart()
if not tInstanceToStart:
continue
self.StartRequestedVAServer(tInstanceToStart)
except KeyboardInterrupt:
print( "Caught keyboard interrupt, quitting" )
# read variant to start self.oLauncherServerSocket.close()
def ReadVariantToStart(self):
try: try:
sVariantName = oConnection.recv( 512 ) self.sVariantName = self.oLauncherConnection.recv( 512 )
if type( sVariantName ) is bytes: if type( self.sVariantName ) is bytes:
sVariantName = sVariantName.decode( 'utf-8' ) self.sVariantName = self.sVariantName.decode( 'utf-8' )
print( "received start request for variant: " + sVariantName ) print( "Received launch request for variant: " + self.sVariantName )
except socket.error: except socket.error:
print( "Error while reading variant" ) print( "Error while reading variant" )
oConnection.close() self.oLauncherConnection.close()
except (KeyboardInterrupt, SystemExit): return None
raise
else: else:
try: try:
tInstance = tVirtualAcousticVersions[sVariantName] tInstance = self.tVirtualAcousticVersions[self.sVariantName]
except KeyError: except KeyError:
tInstance = None tInstance = None
if not tInstance: if not tInstance:
print( 'Requested VA Instance "' + sVariantName + '" not available' ) print( 'Requested VA Instance "' + self.sVariantName + '" not available' )
oConnection.send( b'f' ) self.oLauncherConnection.send( b'f' ) #answer 'requested version not available
oConnection.close() self.oLauncherConnection.close()
else: return None
return tInstance
def StartRequestedVAServer(self, tInstance):
try: try:
sWorkingDir = tInstance["dir"] sWorkingDir = tInstance["dir"]
except KeyError: except KeyError:
sWorkingDir = None sWorkingDir = None
try: try:
sFile = tInstance["file"] self.sVAExecutableFile = tInstance["file"]
if not os.path.isfile( sFile ): if not os.path.isfile( self.sVAExecutableFile ):
if sWorkingDir and os.path.isfile( sWorkingDir + "/" + sFile ): if sWorkingDir and os.path.isfile( sWorkingDir + "/" + self.sVAExecutableFile ):
sFile = sWorkingDir + "/" + sFile self.sVAExecutableFile = sWorkingDir + "/" + self.sVAExecutableFile
else: else:
print( "ERROR: Invalid config for " + sVariantName + " -- file " + sFile + " does not exist" ) print( "ERROR: Invalid config for " + self.sVariantName + " -- file " + self.sVAExecutableFile + " does not exist" )
oConnection.send( b'n' ) self.oLauncherConnection.send( b'n' ) #answer 'binary file cannot be found or invalid'
return
elif sWorkingDir == None: elif sWorkingDir == None:
sWorkingDir = os.path.dirname( sFile ) sWorkingDir = os.path.dirname( self.sVAExecutableFile )
except KeyError: except KeyError:
sFile = None self.sVAExecutableFile = None
print( "ERROR: config for " + sVariantName + " has no valid \"file\" entry" ) print( "ERROR: config for " + self.sVariantName + " has no valid \"file\" entry" )
oConnection.send( b'i' ) self.oLauncherConnection.send( b'i' ) #answer 'invalid file entry in the config'
oConnection.close() self.oLauncherConnection.close()
return
if not self.sVAExecutableFile:
return
if sFile: sCommand = self.sVAExecutableFile
sCommand = sFile
try: try:
sParams = tInstance["params"] sParams = tInstance["params"]
sCommand = sCommand + ' ' + sParams sCommand = sCommand + ' ' + sParams
...@@ -123,45 +176,69 @@ try: ...@@ -123,45 +176,69 @@ try:
try: try:
nSleep = tInstance["sleep"] nSleep = tInstance["sleep"]
except KeyError: except KeyError:
nSleep = nDefaultSleep nSleep = self.nDefaultSleep
# start instance # start instance
print( 'executing "' + sCommand + '"' ) print( 'executing "' + sCommand + '"' )
oProcess = subprocess.Popen( sCommand, cwd = sWorkingDir, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP ) self.oVAProcess = subprocess.Popen( sCommand, cwd = sWorkingDir, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP )
# wait for requested duration before sending the go signal # wait for requested duration before sending the go signal
time.sleep( nSleep ) time.sleep( nSleep )
if oProcess.poll() != None: if self.oVAProcess.poll() != None:
print( "VA Process died - sending abort token" ) print( "VA Process died - sending abort token" )
oConnection.send( b'a' ) self.oLauncherConnection.send( b'a' ) #answer 'VAServer was aborted
self.oLauncherConnection.close()
return
else: else:
print( "sending go token" ) print( "sending go token" )
oConnection.send( b'g' ) self.oLauncherConnection.send( b'g' )#answer 'go, VAServer is correctly started'
self.ListenForRequestsByVAServer()
#if the above terminates a quit request was received:
# kill VA instance
print( "Closing VA instance" )
self.oVAProcess.terminate()
time.sleep( 1 )
self.oVAProcess.kill()
self.oVAProcess = None
#wait until quit command arrives, or the connection closes def ListenForRequestsByVAServer(self):
bContinue = True while True:
oConnection.settimeout( 1.0 )
while bContinue:
try: try:
sResult = oConnection.recv( 128 ) sResult = self.oLauncherConnection.recv( 128 )
if sResult != '': if sResult != '':
#check whether we are about to reveive a file #check whether we are about to reveive a file
sMessage = sResult.decode("utf-8") sMessage = sResult.decode("utf-8")
if sMessage.startswith("file"): if sMessage.startswith("file"):
self.ReceiveFile(sMessage)
else: #NOT sMessage.startswith("file")
print( "Received quit event: "+sMessage )
break
except socket.timeout:
# timeouts are okay
print( "Launcher Socket timeout, keep running anyways" )
except socket.error:
print( "Launcher Connection terminated unexpectedly" )
break
except (KeyboardInterrupt, SystemExit):
raise #re-raise for higher instance to catch
def ReceiveFile(self, sMessage):
aMessageParts = sMessage.split(":") aMessageParts = sMessage.split(":")
iBytesToReceive = int(aMessageParts[2]) iBytesToReceive = int(aMessageParts[2])
Path, Filename = os.path.split(aMessageParts[1]) Path, Filename = os.path.split(aMessageParts[1])
ProjectName = aMessageParts[3] ProjectName = aMessageParts[3]
Fullpath = os.path.join(sCurrentScriptsDirectory, "..", "tmp", ProjectName, Path, "") Fullpath = os.path.join(self.sCurrentScriptsDirectory, "..", "tmp", ProjectName, Path, "")
print("Should receive file: "+Filename+" in path "+Fullpath+ " with "+str(iBytesToReceive)+" bytes") print("Should receive file: "+Filename+" in path "+Fullpath+ " with "+str(iBytesToReceive)+" bytes")
#check whether the file with this exact size already exists #check whether the file with this exact size already exists
if os.path.isfile(Fullpath+Filename) and os.stat(Fullpath+Filename).st_size==iBytesToReceive: if os.path.isfile(Fullpath+Filename) and os.stat(Fullpath+Filename).st_size==iBytesToReceive:
oConnection.send( b'exists' ) self.oLauncherConnection.send( b'exists' )
print("File already exists with this size, so no need for resending") print("File already exists with this size, so no need for resending")
else: #file need to be received else: #file need to be received
...@@ -170,8 +247,7 @@ try: ...@@ -170,8 +247,7 @@ try:
os.makedirs(Fullpath) os.makedirs(Fullpath)
#send acceptance #send acceptance
oConnection.send( b'ack' ) self.oLauncherConnection.send( b'ack' )
#print("Send ack")
#receive file #receive file
iBytesReceived = 0 iBytesReceived = 0
...@@ -179,8 +255,7 @@ try: ...@@ -179,8 +255,7 @@ try:
bReceivingFile = True bReceivingFile = True
while bReceivingFile: while bReceivingFile:
# read 1024 bytes from the socket (receive) # read 1024 bytes from the socket (receive)
bytes_read = oConnection.recv(1024) bytes_read = self.oLauncherConnection.recv(1024)
#print("Read 1024 bytes")
if not bytes_read: if not bytes_read:
# nothing is received # nothing is received
# file transmitting is done # file transmitting is done
...@@ -195,32 +270,16 @@ try: ...@@ -195,32 +270,16 @@ try:
#check whether received file seems ok #check whether received file seems ok
if iBytesReceived == iBytesToReceive: if iBytesReceived == iBytesToReceive:
oConnection.send( b'ack' ) #send acceptance self.oLauncherConnection.send( b'ack' ) #send acceptance
print("File received successfully") print("File received successfully")
else: else:
oConnection.send( b'fail' ) #send failure self.oLauncherConnection.send( b'fail' ) #send failure
print("File receive failed") print("File receive failed")
else: #NOT sMessage.startswith("file")
print( "Received quit event: "+sMessage )
bContinue = False
except socket.timeout:
bContinue = True # timeouts are okay
except socket.error:
print( "Connection terminated unexpectedly" )
bContinue = False
except (KeyboardInterrupt, SystemExit):
raise
# kill VA instance #create an instance of the class
print( "Closing VA instance" ) oLauncher = VirtualAcousticsLauncher()
oProcess.terminate()
time.sleep( 1 )
oProcess.kill()
oProcess = None
except KeyboardInterrupt:
print( "Caught keyboard interrupt, quitting" )
oServer.close()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment