Source code for schrodinger.job.server
"""
Interact with a Job Server.
"""
import json
import os
from typing import NamedTuple
from typing import Union
from schrodinger.utils import subprocess
[docs]def ensure_localhost_server_running():
"""
Makes sure there is a localhost jobserver running to do devtests.
This server is configured in the default location.
"""
proc = subprocess.run(
[jsc(os.environ["SCHRODINGER"]), "local-server-start"],
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE)
if proc.returncode != 0:
raise RuntimeError(
f"localhost job server failed to start with error {proc.stdout}")
[docs]def jsc(schrodinger):
return f"{schrodinger}/jsc"
[docs]class ServerInfo(NamedTuple):
"""
ServerInfo is a serialization of a jobs protobuf ServerInfoResponse.
See "jobs.proto" for more up-to-date details on each of these fields.
It is created manually instead of generated by protoc because this is
currently a niche data structure only used for generating a cert. It's not
worth the time to incorporate the generation into our build steps or to wrap
from c++ using SWIG because the raw data must come serialized from jsc
anyway - see "get_server_info" for details.
"""
# webServerSecret is a deprecated field not relevant to most users.
webServerSecret: str
# hasLicenseChecking indicates whether the server has license checking.
hasLicenseChecking: bool
# hasServerAuth indicates whether the server has LDAP Authentication enabled.
hasServerAuth: bool
# hasSocketAuth indicates whether the server has Unix socket authentication enabled.
hasSocketAuth: bool
# authSocketPath is the path to the unix socket on the job server, if hasSocketAuth is True.
authSocketPath: str
# versionString is the version string for the job server, of the form "55000 revision={git_hash}"
versionString: str
# APIVersion is the API version of the jobserver.
APIVersion: str
# hostname is the hostname of the jobserver as specified on its TLS certificate.
# It must be DNS-resolvable from a client machine in order to make a connection.
hostname: str
# databaseType is the database system used by the job server (either "sqlite" or "postgres")
databaseType: str
# schrodingerInstallation is a path to ANY schrodinger installation known by the job server.
schrodingerInstallation: str
[docs] @classmethod
def from_dict(cls, data: dict) -> "ServerInfo":
"""
Convert a dict to a ServerInfo.
"""
return ServerInfo(**{field: data[field] for field in cls._fields})
[docs] def has_authenticator(self) -> bool:
return self.hasServerAuth or self.hasSocketAuth
[docs]def get_server_info(schrodinger: str, address: str) -> ServerInfo:
"""
Subprocess '$SCHRODINGER/jsc server-info' to get server information.
This must be collected from jsc (the Go gRPC JobServerClient cli) because
the c++ gRPC client doesn't support TLS connections to jobserver until we
already have a cert.
"""
server_info_command = [jsc(schrodinger), "server-info", "--json", address]
proc = subprocess.run(server_info_command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
if proc.returncode:
raise RuntimeError(
f"Could not get server info from job server: {address}.\n"
f"Ran command: '{server_info_command}' with output: '{proc.stdout!r}'"
f"with exit code: '{proc.returncode}.'")
info = decode_to_server_info(proc.stdout)
return info
[docs]def decode_to_server_info(data: Union[str, bytes]) -> ServerInfo:
info_json = json.loads(data)
server_info = ServerInfo.from_dict(info_json)
return server_info