feat: 记录网关可连接性

pull/6582/head
xinwen 2021-07-26 16:32:01 +08:00 committed by 老广
parent d93f3aca51
commit 4085df913b
4 changed files with 52 additions and 19 deletions

View File

@ -33,7 +33,7 @@ class GatewayViewSet(OrgBulkModelViewSet):
model = Gateway
filterset_fields = ("domain__name", "name", "username", "ip", "domain")
search_fields = ("domain__name", "name", "username", "ip")
permission_classes = (IsOrgAdmin,)
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.GatewaySerializer

View File

@ -3,16 +3,19 @@
import socket
import uuid
import random
import re
from django.core.cache import cache
import paramiko
from django.db import models
from django.db.models import TextChoices
from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger
from orgs.mixins.models import OrgModelMixin
from .base import BaseUser
logger = get_logger(__file__)
__all__ = ['Domain', 'Gateway']
@ -39,10 +42,19 @@ class Domain(OrgModelMixin):
return self.gateway_set.filter(is_active=True)
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)
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):
ssh = 'ssh', 'SSH'
@ -60,6 +72,37 @@ class Gateway(BaseUser):
unique_together = [('name', 'org_id')]
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):
if local_port is None:
local_port = self.port
@ -85,6 +128,7 @@ class Gateway(BaseUser):
err = err.format(port=self.port, ip=self.ip)
elif err == 'Authentication failed.':
err = _('Authentication failed')
self.is_connective = False
return False, err
try:
@ -99,7 +143,9 @@ class Gateway(BaseUser):
timeout=5)
except (paramiko.SSHException, paramiko.ssh_exception.SSHException,
paramiko.AuthenticationException, TimeoutError) as e:
self.is_connective = False
return False, str(e)
finally:
client.close()
self.is_connective = True
return True, None

View File

@ -42,6 +42,8 @@ class DomainSerializer(BulkOrgResourceModelSerializer):
class GatewaySerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
is_connective = serializers.BooleanField(required=False)
class Meta:
model = Gateway
fields_mini = ['id', 'name']
@ -50,7 +52,7 @@ class GatewaySerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
]
fields_small = fields_mini + fields_write_only + [
'username', 'ip', 'port', 'protocol',
'is_active',
'is_active', 'is_connective',
'date_created', 'date_updated',
'created_by', 'comment',
]

View File

@ -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