perf: 修改 protcols

pull/8873/head
ibuler 2022-08-05 15:46:36 +08:00
parent 6c57db0897
commit 196e38897f
5 changed files with 36 additions and 70 deletions

View File

@ -6,10 +6,12 @@ from django.db import migrations
def migrate_asset_protocols(apps, schema_editor): def migrate_asset_protocols(apps, schema_editor):
asset_model = apps.get_model('assets', 'Asset') asset_model = apps.get_model('assets', 'Asset')
protocol_model = apps.get_model('assets', 'Protocol') protocol_model = apps.get_model('assets', 'Protocol')
asset_protocol_through = asset_model.protocols.through
count = 0 count = 0
bulk_size = 1000 bulk_size = 1000
print("\nStart migrate asset protocols") print("\nStart migrate asset protocols")
protocol_map = {}
while True: while True:
start = time.time() start = time.time()
assets = asset_model.objects.all()[count:count+bulk_size] assets = asset_model.objects.all()[count:count+bulk_size]
@ -17,15 +19,24 @@ def migrate_asset_protocols(apps, schema_editor):
if not assets: if not assets:
break break
protocols = [] assets_protocols = []
for asset in assets: for asset in assets:
for protocol in asset.protocols.all(): old_protocols = asset._protocols
protocols.append(protocol_model(
asset_id=asset.id, for name_port in old_protocols.split(','):
protocol=protocol.protocol, name_port_list = name_port.split('/')
port=protocol.port, if len(name_port_list) != 2:
)) continue
protocol_model.objects.bulk_create(protocols, ignore_conflicts=True)
name, port = name_port_list
protocol = protocol_map.get(name_port)
if not protocol:
protocol = protocol_model.objects.get_or_create(
defaults={'name': name, 'port': port},
name=name, port=port
)[0]
assets_protocols.append(asset_protocol_through(asset_id=asset.id, protocol_id=protocol.id))
asset_model.protocols.through.objects.bulk_create(assets_protocols, ignore_conflicts=True)
print("Create asset protocols: {}-{} using: {:.2f}s".format( print("Create asset protocols: {}-{} using: {:.2f}s".format(
count - bulk_size, count, time.time()-start count - bulk_size, count, time.time()-start
)) ))

View File

@ -3,70 +3,30 @@
from rest_framework import serializers from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from orgs.mixins.serializers import OrgResourceModelSerializerMixin from orgs.mixins.serializers import OrgResourceModelSerializerMixin
from ...models import Asset, Node, Platform, SystemUser from ...models import Asset, Node, Platform, SystemUser, Protocol, Label
from ..mixin import CategoryDisplayMixin from ..mixin import CategoryDisplayMixin
from ..account import AccountSerializer from ..account import AccountSerializer
__all__ = [ __all__ = [
'AssetSerializer', 'AssetSimpleSerializer', 'MiniAssetSerializer', 'AssetSerializer', 'AssetSimpleSerializer', 'MiniAssetSerializer',
'AssetTaskSerializer', 'AssetsTaskSerializer', 'ProtocolsField', 'AssetTaskSerializer', 'AssetsTaskSerializer',
] ]
class ProtocolField(serializers.RegexField): class AssetProtocolsSerializer(serializers.ModelSerializer):
default_error_messages = { class Meta:
'invalid': _('Protocol format should {}/{}').format('protocol', '1-65535') model = Protocol
} fields = ['id', 'name', 'port']
regex = r'^(\w+)/(\d{1,5})$'
def __init__(self, *args, **kwargs):
super().__init__(self.regex, **kwargs)
def validate_duplicate_protocols(values): class AssetLabelSerializer(serializers.ModelSerializer):
errors = [] class Meta:
names = [] model = Label
fields = ['id', 'name', 'value']
print("Value is: ", values)
for value in values.split(' '):
if not value or '/' not in value:
continue
name = value.split('/')[0]
if name in names:
errors.append(_("Protocol duplicate: {}").format(name))
names.append(name)
errors.append('')
if any(errors):
raise serializers.ValidationError(errors)
class ProtocolsField(serializers.ListField):
default_validators = [validate_duplicate_protocols]
def __init__(self, *args, **kwargs):
kwargs['child'] = ProtocolField()
kwargs['allow_null'] = True
kwargs['allow_empty'] = True
kwargs['min_length'] = 1
kwargs['max_length'] = 32
super().__init__(*args, **kwargs)
def to_representation(self, value):
if not value:
return []
if isinstance(value, str):
return value.split(' ')
return value
def to_internal_value(self, data):
return ' '.join(data)
class AssetSerializer(CategoryDisplayMixin, OrgResourceModelSerializerMixin): class AssetSerializer(CategoryDisplayMixin, OrgResourceModelSerializerMixin):
protocols = ProtocolsField(label=_('Protocols'), required=False, default=['ssh/22'])
domain_display = serializers.ReadOnlyField(source='domain.name', label=_('Domain name')) domain_display = serializers.ReadOnlyField(source='domain.name', label=_('Domain name'))
nodes_display = serializers.ListField( nodes_display = serializers.ListField(
child=serializers.CharField(), label=_('Nodes name'), required=False child=serializers.CharField(), label=_('Nodes name'), required=False
@ -75,10 +35,12 @@ class AssetSerializer(CategoryDisplayMixin, OrgResourceModelSerializerMixin):
child=serializers.CharField(), label=_('Labels name'), child=serializers.CharField(), label=_('Labels name'),
required=False, read_only=True required=False, read_only=True
) )
labels = AssetLabelSerializer(many=True, required=False)
platform_display = serializers.SlugField( platform_display = serializers.SlugField(
source='platform.name', label=_("Platform display"), read_only=True source='platform.name', label=_("Platform display"), read_only=True
) )
accounts = AccountSerializer(many=True, write_only=True, required=False) accounts = AccountSerializer(many=True, write_only=True, required=False)
protocols = AssetProtocolsSerializer(many=True)
""" """
资产的数据结构 资产的数据结构
@ -87,17 +49,16 @@ class AssetSerializer(CategoryDisplayMixin, OrgResourceModelSerializerMixin):
class Meta: class Meta:
model = Asset model = Asset
fields_mini = [ fields_mini = [
'id', 'hostname', 'ip', 'platform', 'protocols' 'id', 'hostname', 'ip',
] ]
fields_small = fields_mini + [ fields_small = fields_mini + [
'protocol', 'port', 'is_active', 'is_active', 'number', 'comment',
'public_ip', 'number', 'comment',
] ]
fields_fk = [ fields_fk = [
'domain', 'domain_display', 'platform', 'domain', 'domain_display', 'platform', 'platform', 'platform_display',
] ]
fields_m2m = [ fields_m2m = [
'nodes', 'nodes_display', 'labels', 'labels_display', 'accounts' 'nodes', 'nodes_display', 'labels', 'labels_display', 'accounts', 'protocols',
] ]
read_only_fields = [ read_only_fields = [
'category', 'category_display', 'type', 'type_display', 'category', 'category_display', 'type', 'type_display',

View File

@ -3,8 +3,6 @@ from django.core.validators import RegexValidator
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from assets.models import Platform from assets.models import Platform
from assets.serializers.asset import ProtocolsField
from assets.const import Protocol
from .mixin import CategoryDisplayMixin from .mixin import CategoryDisplayMixin
__all__ = ['PlatformSerializer'] __all__ = ['PlatformSerializer']
@ -12,7 +10,7 @@ __all__ = ['PlatformSerializer']
class PlatformSerializer(CategoryDisplayMixin, serializers.ModelSerializer): class PlatformSerializer(CategoryDisplayMixin, serializers.ModelSerializer):
meta = serializers.DictField(required=False, allow_null=True, label=_('Meta')) meta = serializers.DictField(required=False, allow_null=True, label=_('Meta'))
protocols_default = ProtocolsField(label=_('Protocols'), required=False) protocols_default = serializers.ListField(label=_('Protocols'), required=False)
type_limits = serializers.ReadOnlyField(required=False, read_only=True) type_limits = serializers.ReadOnlyField(required=False, read_only=True)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View File

@ -8,7 +8,6 @@ from common.utils.random import random_string
from assets.models import Asset, SystemUser, Gateway, Domain, CommandFilterRule from assets.models import Asset, SystemUser, Gateway, Domain, CommandFilterRule
from users.models import User from users.models import User
from applications.models import Application from applications.models import Application
from assets.serializers import ProtocolsField
from perms.serializers.base import ActionsField from perms.serializers.base import ActionsField
@ -122,7 +121,6 @@ class ConnectionTokenUserSerializer(serializers.ModelSerializer):
class ConnectionTokenAssetSerializer(serializers.ModelSerializer): class ConnectionTokenAssetSerializer(serializers.ModelSerializer):
protocols = ProtocolsField(label='Protocols', read_only=True)
class Meta: class Meta:
model = Asset model = Asset

View File

@ -5,7 +5,6 @@ from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from assets.models import Node, SystemUser, Asset, Platform from assets.models import Node, SystemUser, Asset, Platform
from assets.serializers import ProtocolsField
from perms.serializers.base import ActionsField from perms.serializers.base import ActionsField
__all__ = [ __all__ = [
@ -38,7 +37,6 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
""" """
被授权资产的数据结构 被授权资产的数据结构
""" """
protocols = ProtocolsField(label=_('Protocols'), required=False, read_only=True)
platform = serializers.SlugRelatedField( platform = serializers.SlugRelatedField(
slug_field='name', queryset=Platform.objects.all(), label=_("Platform") slug_field='name', queryset=Platform.objects.all(), label=_("Platform")
) )