Check if registry connection can be made

This commit is contained in:
zandercymatics 2023-10-12 14:38:49 -06:00
parent c4d2950ac9
commit dfec8c200e
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
2 changed files with 54 additions and 11 deletions

View file

@ -15,6 +15,7 @@ from django.conf import settings
from .cert import Cert, Key from .cert import Cert, Key
from .errors import LoginError, RegistryError from .errors import LoginError, RegistryError
from .socket import Socket
from .utility.pool import EppConnectionPool from .utility.pool import EppConnectionPool
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -41,7 +42,6 @@ class EPPLibWrapper:
def __init__(self) -> None: def __init__(self) -> None:
"""Initialize settings which will be used for all connections.""" """Initialize settings which will be used for all connections."""
# prepare (but do not send) a Login command # prepare (but do not send) a Login command
self._login = commands.Login( self._login = commands.Login(
cl_id=settings.SECRET_REGISTRY_CL_ID, cl_id=settings.SECRET_REGISTRY_CL_ID,
@ -51,6 +51,7 @@ class EPPLibWrapper:
"urn:ietf:params:xml:ns:contact-1.0", "urn:ietf:params:xml:ns:contact-1.0",
], ],
) )
# establish a client object with a TCP socket transport # establish a client object with a TCP socket transport
self._client = Client( self._client = Client(
SocketTransport( SocketTransport(
@ -71,19 +72,23 @@ class EPPLibWrapper:
# Occasionally pings the registry to keep the connection alive # Occasionally pings the registry to keep the connection alive
"keepalive": settings.POOL_KEEP_ALIVE, "keepalive": settings.POOL_KEEP_ALIVE,
} }
self._pool = EppConnectionPool(
client=self._client, login=self._login, options=options self._pool = None
) if not settings.DEBUG or self._test_registry_connection_success():
self._pool = EppConnectionPool(
client=self._client, login=self._login, options=options
)
else:
logger.warning("Cannot contact the Registry")
# TODO - signal that the app may need to restart?
def _send(self, command): def _send(self, command):
"""Helper function used by `send`.""" """Helper function used by `send`."""
cmd_type = command.__class__.__name__ cmd_type = command.__class__.__name__
try: try:
# We won't have an EPP connection locally, if self._pool is None:
# shortcut this and raise an err
# TODO - implement a timeout in _pool.get()
if settings.DEBUG:
raise LoginError raise LoginError
# TODO - add a timeout
with self._pool.get() as connection: with self._pool.get() as connection:
response = connection.send(command) response = connection.send(command)
except (ValueError, ParsingError) as err: except (ValueError, ParsingError) as err:
@ -127,6 +132,18 @@ class EPPLibWrapper:
else: # don't try again else: # don't try again
raise err raise err
def _test_registry_connection_success(self):
"""Check that determines if our login
credentials are valid, and/or if the Registrar
can be contacted
"""
socket = Socket(self._login, self._client)
can_login = False
# Something went wrong if this doesn't exist
if hasattr(socket, "test_connection_success"):
can_login = socket.test_connection_success()
return can_login
try: try:
# Initialize epplib # Initialize epplib

View file

@ -1,7 +1,9 @@
import logging import logging
from time import sleep
try: try:
from epplib import commands from epplib import commands
from epplib.client import Client
except ImportError: except ImportError:
pass pass
@ -14,7 +16,7 @@ logger = logging.getLogger(__name__)
class Socket: class Socket:
"""Context manager which establishes a TCP connection with registry.""" """Context manager which establishes a TCP connection with registry."""
def __init__(self, client, login) -> None: def __init__(self, client: commands.Login, login: Client) -> None:
"""Save the epplib client and login details.""" """Save the epplib client and login details."""
self.client = client self.client = client
self.login = login self.login = login
@ -27,15 +29,39 @@ class Socket:
"""Runs disconnect(), which closes a connection with EPPLib.""" """Runs disconnect(), which closes a connection with EPPLib."""
self.disconnect() self.disconnect()
def connect(self): def connect(self, pass_response_only=False):
"""Use epplib to connect.""" """Use epplib to connect."""
self.client.connect() self.client.connect()
response = self.client.send(self.login) response = self.client.send(self.login)
if response.code >= 2000: if self.is_login_error(response.code):
self.client.close() self.client.close()
raise LoginError(response.msg) raise LoginError(response.msg)
return self.client return self.client
def is_login_error(self, code):
return code >= 2000
def test_connection_success(self):
"""Tests if a successful connection can be made with the registry"""
# Something went wrong if this doesn't exist
if not hasattr(self.client, "connect"):
return False
counter = 0 # we'll try 3 times
while True:
try:
self.client.connect()
response = self.client.send(self.login)
except LoginError as err:
if err.should_retry() and counter < 3:
counter += 1
sleep((counter * 50) / 1000) # sleep 50 ms to 150 ms
else: # don't try again
return False
else:
self.disconnect()
return not self.is_login_error(response.code)
def disconnect(self): def disconnect(self):
"""Close the connection.""" """Close the connection."""
try: try: