mirror of https://github.com/jumpserver/jumpserver
feat: 记录网关可连接性
parent
d93f3aca51
commit
4085df913b
|
@ -33,7 +33,7 @@ class GatewayViewSet(OrgBulkModelViewSet):
|
||||||
model = Gateway
|
model = Gateway
|
||||||
filterset_fields = ("domain__name", "name", "username", "ip", "domain")
|
filterset_fields = ("domain__name", "name", "username", "ip", "domain")
|
||||||
search_fields = ("domain__name", "name", "username", "ip")
|
search_fields = ("domain__name", "name", "username", "ip")
|
||||||
permission_classes = (IsOrgAdmin,)
|
permission_classes = (IsOrgAdminOrAppUser,)
|
||||||
serializer_class = serializers.GatewaySerializer
|
serializer_class = serializers.GatewaySerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,19 @@
|
||||||
import socket
|
import socket
|
||||||
import uuid
|
import uuid
|
||||||
import random
|
import random
|
||||||
import re
|
|
||||||
|
|
||||||
|
from django.core.cache import cache
|
||||||
import paramiko
|
import paramiko
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import TextChoices
|
from django.db.models import TextChoices
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from common.utils import get_logger
|
||||||
from orgs.mixins.models import OrgModelMixin
|
from orgs.mixins.models import OrgModelMixin
|
||||||
from .base import BaseUser
|
from .base import BaseUser
|
||||||
|
|
||||||
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
__all__ = ['Domain', 'Gateway']
|
__all__ = ['Domain', 'Gateway']
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,10 +42,19 @@ class Domain(OrgModelMixin):
|
||||||
return self.gateway_set.filter(is_active=True)
|
return self.gateway_set.filter(is_active=True)
|
||||||
|
|
||||||
def random_gateway(self):
|
def random_gateway(self):
|
||||||
|
gateways = [gw for gw in self.gateways if gw.is_connective]
|
||||||
|
if gateways:
|
||||||
|
return random.choice(gateways)
|
||||||
|
else:
|
||||||
|
logger.warn(f'Gateway all bad. domain={self}, gateway_num={len(self.gateways)}.')
|
||||||
return random.choice(self.gateways)
|
return random.choice(self.gateways)
|
||||||
|
|
||||||
|
|
||||||
class Gateway(BaseUser):
|
class Gateway(BaseUser):
|
||||||
|
UNCONNECTIVE_KEY_TMPL = 'asset_unconnective_gateway_{}'
|
||||||
|
UNCONNECTIVE_SILENCE_PERIOD_KEY_TMPL = 'asset_unconnective_gateway_silence_period_{}'
|
||||||
|
UNCONNECTIVE_SILENCE_PERIOD_BEGIN_VALUE = 60 * 5
|
||||||
|
|
||||||
class Protocol(TextChoices):
|
class Protocol(TextChoices):
|
||||||
ssh = 'ssh', 'SSH'
|
ssh = 'ssh', 'SSH'
|
||||||
|
|
||||||
|
@ -60,6 +72,37 @@ class Gateway(BaseUser):
|
||||||
unique_together = [('name', 'org_id')]
|
unique_together = [('name', 'org_id')]
|
||||||
verbose_name = _("Gateway")
|
verbose_name = _("Gateway")
|
||||||
|
|
||||||
|
def set_unconnective(self):
|
||||||
|
unconnective_key = self.UNCONNECTIVE_KEY_TMPL.format(self.id)
|
||||||
|
unconnective_silence_period_key = self.UNCONNECTIVE_SILENCE_PERIOD_KEY_TMPL.format(self.id)
|
||||||
|
|
||||||
|
unconnective_silence_period = cache.get(unconnective_silence_period_key,
|
||||||
|
self.UNCONNECTIVE_SILENCE_PERIOD_BEGIN_VALUE)
|
||||||
|
cache.set(unconnective_silence_period_key, unconnective_silence_period * 2)
|
||||||
|
cache.set(unconnective_key, unconnective_silence_period, unconnective_silence_period)
|
||||||
|
|
||||||
|
def set_connective(self):
|
||||||
|
unconnective_key = self.UNCONNECTIVE_KEY_TMPL.format(self.id)
|
||||||
|
unconnective_silence_period_key = self.UNCONNECTIVE_SILENCE_PERIOD_KEY_TMPL.format(self.id)
|
||||||
|
|
||||||
|
cache.delete(unconnective_key)
|
||||||
|
cache.delete(unconnective_silence_period_key)
|
||||||
|
|
||||||
|
def get_is_unconnective(self):
|
||||||
|
unconnective_key = self.UNCONNECTIVE_KEY_TMPL.format(self.id)
|
||||||
|
return cache.get(unconnective_key, False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_connective(self):
|
||||||
|
return not self.get_is_unconnective()
|
||||||
|
|
||||||
|
@is_connective.setter
|
||||||
|
def is_connective(self, value):
|
||||||
|
if value:
|
||||||
|
self.set_connective()
|
||||||
|
else:
|
||||||
|
self.set_unconnective()
|
||||||
|
|
||||||
def test_connective(self, local_port=None):
|
def test_connective(self, local_port=None):
|
||||||
if local_port is None:
|
if local_port is None:
|
||||||
local_port = self.port
|
local_port = self.port
|
||||||
|
@ -85,6 +128,7 @@ class Gateway(BaseUser):
|
||||||
err = err.format(port=self.port, ip=self.ip)
|
err = err.format(port=self.port, ip=self.ip)
|
||||||
elif err == 'Authentication failed.':
|
elif err == 'Authentication failed.':
|
||||||
err = _('Authentication failed')
|
err = _('Authentication failed')
|
||||||
|
self.is_connective = False
|
||||||
return False, err
|
return False, err
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -99,7 +143,9 @@ class Gateway(BaseUser):
|
||||||
timeout=5)
|
timeout=5)
|
||||||
except (paramiko.SSHException, paramiko.ssh_exception.SSHException,
|
except (paramiko.SSHException, paramiko.ssh_exception.SSHException,
|
||||||
paramiko.AuthenticationException, TimeoutError) as e:
|
paramiko.AuthenticationException, TimeoutError) as e:
|
||||||
|
self.is_connective = False
|
||||||
return False, str(e)
|
return False, str(e)
|
||||||
finally:
|
finally:
|
||||||
client.close()
|
client.close()
|
||||||
|
self.is_connective = True
|
||||||
return True, None
|
return True, None
|
||||||
|
|
|
@ -42,6 +42,8 @@ class DomainSerializer(BulkOrgResourceModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class GatewaySerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
class GatewaySerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
|
is_connective = serializers.BooleanField(required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Gateway
|
model = Gateway
|
||||||
fields_mini = ['id', 'name']
|
fields_mini = ['id', 'name']
|
||||||
|
@ -50,7 +52,7 @@ class GatewaySerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
]
|
]
|
||||||
fields_small = fields_mini + fields_write_only + [
|
fields_small = fields_mini + fields_write_only + [
|
||||||
'username', 'ip', 'port', 'protocol',
|
'username', 'ip', 'port', 'protocol',
|
||||||
'is_active',
|
'is_active', 'is_connective',
|
||||||
'date_created', 'date_updated',
|
'date_created', 'date_updated',
|
||||||
'created_by', 'comment',
|
'created_by', 'comment',
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
from django.http.request import HttpRequest
|
|
||||||
from django.http.response import HttpResponse
|
|
||||||
|
|
||||||
from orgs.utils import current_org
|
|
||||||
|
|
||||||
|
|
||||||
class RequestLogMiddleware:
|
|
||||||
def __init__(self, get_response):
|
|
||||||
self.get_response = get_response
|
|
||||||
|
|
||||||
def __call__(self, request: HttpRequest):
|
|
||||||
print(f'Request {request.method} --> ', request.get_raw_uri())
|
|
||||||
response: HttpResponse = self.get_response(request)
|
|
||||||
print(f'Response {current_org.name} {request.method} {response.status_code} --> ', request.get_raw_uri())
|
|
||||||
return response
|
|
Loading…
Reference in New Issue