mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
197 lines
7.5 KiB
Python
197 lines
7.5 KiB
Python
import grpc
|
|
import os
|
|
import sys
|
|
import socket
|
|
import logging
|
|
import time
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'generated'))
|
|
import App_pb2
|
|
import App_pb2_grpc
|
|
from Definitions_pb2 import Empty
|
|
|
|
import RiaVersionInfo
|
|
|
|
from rips.Commands import Commands
|
|
from rips.Project import Project
|
|
|
|
class Instance:
|
|
"""The ResInsight Instance class. Use to launch or find existing ResInsight instances
|
|
|
|
Attributes:
|
|
launched (bool): Tells us whether the application was launched as a new process.
|
|
If the application was launched we may need to close it when exiting the script.
|
|
commands (Commands): Command executor. Set when creating an instance.
|
|
project (Project): Current project in ResInsight.
|
|
Set when creating an instance and updated when opening/closing projects.
|
|
"""
|
|
|
|
@staticmethod
|
|
def __is_port_in_use(port):
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
s.settimeout(0.2)
|
|
return s.connect_ex(('localhost', port)) == 0
|
|
|
|
@staticmethod
|
|
def launch(resinsight_executable = '', console = False, launch_port = -1, command_line_parameters=[]):
|
|
""" Launch a new Instance of ResInsight. This requires the environment variable
|
|
RESINSIGHT_EXECUTABLE to be set or the parameter resinsight_executable to be provided.
|
|
The RESINSIGHT_GRPC_PORT environment variable can be set to an alternative port number.
|
|
|
|
Args:
|
|
resinsight_executable (str): Path to a valid ResInsight executable. If set
|
|
will take precedence over what is provided in the RESINSIGHT_EXECUTABLE
|
|
environment variable.
|
|
console (bool): If True, launch as console application, without GUI.
|
|
launch_port(int): If -1 will use the default port of 50051 or look for RESINSIGHT_GRPC_PORT
|
|
if anything else, ResInsight will try to launch with this port
|
|
command_line_parameters(list): Additional command line parameters as string entries in the list.
|
|
Returns:
|
|
Instance: an instance object if it worked. None if not.
|
|
"""
|
|
|
|
port = 50051
|
|
port_env = os.environ.get('RESINSIGHT_GRPC_PORT')
|
|
if port_env:
|
|
port = int(port_env)
|
|
if launch_port is not -1:
|
|
port = launch_port
|
|
|
|
if not resinsight_executable:
|
|
resinsight_executable = os.environ.get('RESINSIGHT_EXECUTABLE')
|
|
if not resinsight_executable:
|
|
print('ERROR: Could not launch ResInsight because the environment variable'
|
|
' RESINSIGHT_EXECUTABLE is not set')
|
|
return None
|
|
|
|
while Instance.__is_port_in_use(port):
|
|
port += 1
|
|
|
|
print('Port ' + str(port))
|
|
print('Trying to launch', resinsight_executable)
|
|
|
|
if isinstance(command_line_parameters, str):
|
|
command_line_parameters = [str]
|
|
|
|
parameters = ["ResInsight", "--server", str(port)] + command_line_parameters
|
|
if console:
|
|
print("Launching as console app")
|
|
parameters.append("--console")
|
|
|
|
# Stringify all parameters
|
|
for i in range(0, len(parameters)):
|
|
parameters[i] = str(parameters[i])
|
|
|
|
pid = os.spawnv(os.P_NOWAIT, resinsight_executable, parameters)
|
|
if pid:
|
|
instance = Instance(port=port, launched=True)
|
|
return instance
|
|
return None
|
|
|
|
@staticmethod
|
|
def find(start_port = 50051, end_port = 50071):
|
|
""" Search for an existing Instance of ResInsight by testing ports.
|
|
|
|
By default we search from port 50051 to 50071 or if the environment
|
|
variable RESINSIGHT_GRPC_PORT is set we search
|
|
RESINSIGHT_GRPC_PORT to RESINSIGHT_GRPC_PORT+20
|
|
|
|
Args:
|
|
start_port (int): start searching from this port
|
|
end_port (int): search up to but not including this port
|
|
"""
|
|
port_env = os.environ.get('RESINSIGHT_GRPC_PORT')
|
|
if port_env:
|
|
start_port = int(port_env)
|
|
end_port = start_port + 20
|
|
|
|
for try_port in range(start_port, end_port):
|
|
if Instance.__is_port_in_use(try_port):
|
|
return Instance(port=try_port)
|
|
|
|
print('Error: Could not find any ResInsight instances responding between ports ' + str(start_port) + ' and ' + str(end_port))
|
|
return None
|
|
|
|
def __check_version(self):
|
|
try:
|
|
major_version_ok = self.major_version() == int(RiaVersionInfo.RESINSIGHT_MAJOR_VERSION)
|
|
minor_version_ok = self.minor_version() == int(RiaVersionInfo.RESINSIGHT_MINOR_VERSION)
|
|
return True, major_version_ok and minor_version_ok
|
|
except:
|
|
return False, False
|
|
|
|
def __init__(self, port = 50051, launched = False):
|
|
""" Attempts to connect to ResInsight at aa specific port on localhost
|
|
|
|
Args:
|
|
port(int): port number
|
|
"""
|
|
logging.basicConfig()
|
|
location = "localhost:" + str(port)
|
|
|
|
self.channel = grpc.insecure_channel(location, options=[('grpc.enable_http_proxy', False)])
|
|
self.launched = launched
|
|
|
|
# Main version check package
|
|
self.app = self.app = App_pb2_grpc.AppStub(self.channel)
|
|
|
|
connection_ok = False
|
|
version_ok = False
|
|
|
|
if self.launched:
|
|
for i in range(0, 10):
|
|
connection_ok, version_ok = self.__check_version()
|
|
if connection_ok:
|
|
break
|
|
time.sleep(1.0)
|
|
else:
|
|
connection_ok, version_ok = self.__check_version()
|
|
|
|
if not connection_ok:
|
|
if self.launched:
|
|
raise Exception('Error: Could not connect to resinsight at ', location, ' after trying 10 times with 1 second apart')
|
|
else:
|
|
raise Exception('Error: Could not connect to resinsight at ', location)
|
|
exit(1)
|
|
if not version_ok:
|
|
raise Exception('Error: Wrong Version of ResInsight at ', location)
|
|
|
|
# Service packages
|
|
self.commands = Commands(self.channel)
|
|
self.project = Project(self.channel)
|
|
|
|
path = os.getcwd()
|
|
self.commands.set_start_dir(path=path)
|
|
|
|
def __version_message(self):
|
|
return self.app.GetVersion(Empty())
|
|
|
|
def major_version(self):
|
|
"""Get an integer with the major version number"""
|
|
return self.__version_message().major_version
|
|
|
|
def minor_version(self):
|
|
"""Get an integer with the minor version number"""
|
|
return self.__version_message().minor_version
|
|
|
|
def patch_version(self):
|
|
"""Get an integer with the patch version number"""
|
|
return self.__version_message().patch_version
|
|
|
|
def version_string(self):
|
|
"""Get a full version string, i.e. 2019.04.01"""
|
|
return str(self.major_version()) + "." + str(self.minor_version()) + "." + str(self.patch_version())
|
|
|
|
def exit(self):
|
|
"""Tell ResInsight instance to quit"""
|
|
print("Telling ResInsight to Exit")
|
|
return self.app.Exit(Empty())
|
|
|
|
def is_console(self):
|
|
"""Returns true if the connected ResInsight instance is a console app"""
|
|
return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('CONSOLE_APPLICATION')
|
|
|
|
def is_gui(self):
|
|
"""Returns true if the connected ResInsight instance is a GUI app"""
|
|
return self.app.GetRuntimeInfo(Empty()).app_type == App_pb2.ApplicationTypeEnum.Value('GUI_APPLICATION')
|