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" )
self.readConfig()
self.openLauncherServerSocket()
self.runLauncher()
sHostConfigurationFile = "VirtualAcousticStarterConfig." + socket.gethostname() + ".py"
sGeneralConfigurationFile = "VirtualAcousticStarterConfig.py"
sCurrentScriptsDirectory = os.path.dirname( os.path.realpath( sys.argv[0] ) )
def readConfig(self):
sHostConfigurationFile = "VirtualAcousticStarterConfig." + socket.gethostname() + ".json"
sGeneralConfigurationFile = "VirtualAcousticStarterConfig.json"
sUsedConfigFile = ""
#check which config file exists and load it
if os.path.isfile( sHostConfigurationFile ):
exec( compile( open( sHostConfigurationFile, "rb" ).read(), sHostConfigurationFile, 'exec' ) )
print("Using config: " + sHostConfigurationFile)
elif os.path.isfile( sCurrentScriptsDirectory + "/" + sHostConfigurationFile ):
exec( compile( open( sCurrentScriptsDirectory + "/" + sHostConfigurationFile, "rb" ).read(), sCurrentScriptsDirectory + "/" + sHostConfigurationFile, 'exec' ) )
print("Using config: " + sCurrentScriptsDirectory + "/" + sHostConfigurationFile)
sUsedConfigFile = sHostConfigurationFile
elif os.path.isfile( self.sCurrentScriptsDirectory + "/" + sHostConfigurationFile ):
sUsedConfigFile = self.sCurrentScriptsDirectory + "/" + sHostConfigurationFile
elif os.path.isfile( sGeneralConfigurationFile ):
exec( compile( open( sGeneralConfigurationFile, "rb" ).read(), sGeneralConfigurationFile, 'exec' ) )
print("Using config: " + sGeneralConfigurationFile)
elif os.path.isfile( sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile ):
exec( compile( open( sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile, "rb" ).read(), sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile, 'exec' ) )
print("Using config: " + sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile)
sUsedConfigFile = sGeneralConfigurationFile
elif os.path.isfile( self.sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile ):
sUsedConfigFile = self.sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile
else:
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:
tVirtualAcousticVersions
sLocalIP
nLocalPort
nDefaultSleep
except NameError:
print( "ERROR: configuration did not define required variables: tVirtualAcousticVersions, sLocalIP, nLocalPort, nDefaultSleep" )
sys.exit( 5 )
print( "Creating server socket at " + sLocalIP + ":" + str( nLocalPort ) )
oServer = socket.socket()
if sLocalIP == "":
sLocalIP = socket.gethostname()
self.tVirtualAcousticVersions = json_config["tVirtualAcousticVersions"]
self.sLocalIP = json_config["sLocalIP"]
self.nLocalPort = json_config["nLocalPort"]
self.nDefaultSleep = json_config["nDefaultSleep"]
except KeyError as e:
print( "ERROR reading the json config. Missing " + str(e.args[0]) )
sys.exit( ErrorCodes.ERROR_INCOMPLETE_CONFIG )
def openLauncherServerSocket(self):
print( "Creating server socket at " + self.sLocalIP + ":" + str( self.nLocalPort ) )
self.oLauncherServerSocket = socket.socket()
if self.sLocalIP == "":
self.sLocalIP = socket.gethostname()
try:
oServer.bind( ( sLocalIP, nLocalPort ) )
oServer.listen( 3 )
self.oLauncherServerSocket.bind( ( self.sLocalIP, self.nLocalPort ) )
self.oLauncherServerSocket.listen( 3 )
except socket.error:
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:
print( "Waiting for connection..." )
oConnection = None
while not oConnection:
print( "Waiting for launcher connection..." )
self.oLauncherConnection = None
while not self.oLauncherConnection:
try:
oConnection, sAddress = oServer.accept()
self.oLauncherConnection, sAddress = self.oLauncherServerSocket.accept()
except socket.timeout:
oConnection = None
self.oLauncherConnection = None
except socket.error:
print( "Error while listening for connection" )
sys.exit( 2 )
print( "Error while listening for launcher connection" )
sys.exit( ErrorCodes.ERROR_CONNECTING_SOCKET )
except (KeyboardInterrupt, SystemExit):
raise
raise #re-raising the received exception
print( "Connection received from " + sAddress[0] )
if oProcess:
if self.oVAProcess:
print( "Closing current VA instance" )
oProcess.kill()
oProcess = None
self.oVAProcess.kill()
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:
sVariantName = oConnection.recv( 512 )
if type( sVariantName ) is bytes:
sVariantName = sVariantName.decode( 'utf-8' )
print( "received start request for variant: " + sVariantName )
self.sVariantName = self.oLauncherConnection.recv( 512 )
if type( self.sVariantName ) is bytes:
self.sVariantName = self.sVariantName.decode( 'utf-8' )
print( "Received launch request for variant: " + self.sVariantName )
except socket.error:
print( "Error while reading variant" )
oConnection.close()
except (KeyboardInterrupt, SystemExit):
raise
self.oLauncherConnection.close()
return None
else:
try:
tInstance = tVirtualAcousticVersions[sVariantName]
tInstance = self.tVirtualAcousticVersions[self.sVariantName]
except KeyError:
tInstance = None
if not tInstance:
print( 'Requested VA Instance "' + sVariantName + '" not available' )
oConnection.send( b'f' )
oConnection.close()
else:
print( 'Requested VA Instance "' + self.sVariantName + '" not available' )
self.oLauncherConnection.send( b'f' ) #answer 'requested version not available
self.oLauncherConnection.close()
return None
return tInstance
def StartRequestedVAServer(self, tInstance):
try:
sWorkingDir = tInstance["dir"]
except KeyError:
sWorkingDir = None
try:
sFile = tInstance["file"]
if not os.path.isfile( sFile ):
if sWorkingDir and os.path.isfile( sWorkingDir + "/" + sFile ):
sFile = sWorkingDir + "/" + sFile
self.sVAExecutableFile = tInstance["file"]
if not os.path.isfile( self.sVAExecutableFile ):
if sWorkingDir and os.path.isfile( sWorkingDir + "/" + self.sVAExecutableFile ):
self.sVAExecutableFile = sWorkingDir + "/" + self.sVAExecutableFile
else:
print( "ERROR: Invalid config for " + sVariantName + " -- file " + sFile + " does not exist" )
oConnection.send( b'n' )
print( "ERROR: Invalid config for " + self.sVariantName + " -- file " + self.sVAExecutableFile + " does not exist" )
self.oLauncherConnection.send( b'n' ) #answer 'binary file cannot be found or invalid'
return
elif sWorkingDir == None:
sWorkingDir = os.path.dirname( sFile )
sWorkingDir = os.path.dirname( self.sVAExecutableFile )
except KeyError:
sFile = None
print( "ERROR: config for " + sVariantName + " has no valid \"file\" entry" )
oConnection.send( b'i' )
oConnection.close()
self.sVAExecutableFile = None
print( "ERROR: config for " + self.sVariantName + " has no valid \"file\" entry" )
self.oLauncherConnection.send( b'i' ) #answer 'invalid file entry in the config'
self.oLauncherConnection.close()
return
if not self.sVAExecutableFile:
return
if sFile:
sCommand = sFile
sCommand = self.sVAExecutableFile
try:
sParams = tInstance["params"]
sCommand = sCommand + ' ' + sParams
......@@ -123,45 +176,69 @@ try:
try:
nSleep = tInstance["sleep"]
except KeyError:
nSleep = nDefaultSleep
nSleep = self.nDefaultSleep
# start instance
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
time.sleep( nSleep )
if oProcess.poll() != None:
if self.oVAProcess.poll() != None:
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:
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
bContinue = True
oConnection.settimeout( 1.0 )
while bContinue:
def ListenForRequestsByVAServer(self):
while True:
try:
sResult = oConnection.recv( 128 )
sResult = self.oLauncherConnection.recv( 128 )
if sResult != '':
#check whether we are about to reveive a file
sMessage = sResult.decode("utf-8")
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(":")
iBytesToReceive = int(aMessageParts[2])
Path, Filename = os.path.split(aMessageParts[1])
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")
#check whether the file with this exact size already exists
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")
else: #file need to be received
......@@ -170,8 +247,7 @@ try:
os.makedirs(Fullpath)
#send acceptance
oConnection.send( b'ack' )
#print("Send ack")
self.oLauncherConnection.send( b'ack' )
#receive file
iBytesReceived = 0
......@@ -179,8 +255,7 @@ try:
bReceivingFile = True
while bReceivingFile:
# read 1024 bytes from the socket (receive)
bytes_read = oConnection.recv(1024)
#print("Read 1024 bytes")
bytes_read = self.oLauncherConnection.recv(1024)
if not bytes_read:
# nothing is received
# file transmitting is done
......@@ -195,32 +270,16 @@ try:
#check whether received file seems ok
if iBytesReceived == iBytesToReceive:
oConnection.send( b'ack' ) #send acceptance
self.oLauncherConnection.send( b'ack' ) #send acceptance
print("File received successfully")
else:
oConnection.send( b'fail' ) #send failure
self.oLauncherConnection.send( b'fail' ) #send failure
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
print( "Closing VA instance" )
oProcess.terminate()
time.sleep( 1 )
oProcess.kill()
oProcess = None
#create an instance of the class
oLauncher = VirtualAcousticsLauncher()
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