Merge pull request #3833 from jumpserver/dev

Dev
pull/3883/head
BaiJiangJie 2020-03-27 10:48:09 +08:00 committed by GitHub
commit b4c3471d2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 41 deletions

View File

@ -154,8 +154,8 @@ class AssetUserManager:
@staticmethod
def create(**kwargs):
authbook = AuthBook(**kwargs)
authbook.save()
# 使用create方法创建AuthBook对象解决并发创建问题添加锁机制
authbook = AuthBook.create(**kwargs)
return authbook
def __getattr__(self, item):

View File

@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
#
from django.db import models
from django.db import models, transaction
from django.db.models import Max
from django.core.cache import cache
from django.utils.translation import ugettext_lazy as _
from orgs.mixins.models import OrgManager
@ -11,8 +13,8 @@ __all__ = ['AuthBook']
class AuthBookQuerySet(models.QuerySet):
def latest_version(self):
return self.filter(is_latest=True)
def delete(self):
raise PermissionError("Bulk delete authbook deny")
class AuthBookManager(OrgManager):
@ -33,37 +35,42 @@ class AuthBook(BaseUser):
class Meta:
verbose_name = _('AuthBook')
def set_to_latest(self):
self.remove_pre_latest()
self.is_latest = True
self.save()
def get_pre_latest(self):
pre_obj = self.__class__.objects.filter(
username=self.username, asset=self.asset
).latest_version().first()
return pre_obj
def remove_pre_latest(self):
pre_obj = self.get_pre_latest()
if pre_obj:
pre_obj.is_latest = False
pre_obj.save()
def set_version(self):
pre_obj = self.get_pre_latest()
if pre_obj:
self.version = pre_obj.version + 1
else:
self.version = 1
self.save()
def get_related_assets(self):
return [self.asset]
def generate_id_with_asset(self, asset):
return self.id
@classmethod
def get_max_version(cls, username, asset):
version_max = cls.objects.filter(username=username, asset=asset) \
.aggregate(Max('version'))
version_max = version_max['version__max'] or 0
return version_max
@classmethod
def create(cls, **kwargs):
"""
使用并发锁机制创建AuthBook对象, (主要针对并发创建 username, asset 相同的对象时)
并更新其他对象的 is_latest=False (其他对象: 与当前对象的 username, asset 相同)
同时设置自己的 is_latest=True, version=max_version + 1
"""
username = kwargs['username']
asset = kwargs['asset']
key_lock = 'KEY_LOCK_CREATE_AUTH_BOOK_{}_{}'.format(username, asset.id)
with cache.lock(key_lock):
with transaction.atomic():
cls.objects.filter(
username=username, asset=asset, is_latest=True
).update(is_latest=False)
max_version = cls.get_max_version(username, asset)
kwargs.update({
'version': max_version + 1,
'is_latest': True
})
obj = cls.objects.create(**kwargs)
return obj
@property
def connectivity(self):
return self.get_asset_connectivity(self.asset)

View File

@ -37,7 +37,6 @@ class AssetUserWriteSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializ
if not validated_data.get("name") and validated_data.get("username"):
validated_data["name"] = validated_data["username"]
instance = AssetUserManager.create(**validated_data)
instance.set_to_latest()
return instance

View File

@ -15,7 +15,6 @@ from .utils import TreeService
from .tasks import (
update_assets_hardware_info_util,
test_asset_connectivity_util,
push_system_user_to_assets,
push_system_user_to_assets_manual,
push_system_user_to_assets,
add_nodes_assets_to_system_users
@ -235,9 +234,3 @@ def on_node_update_or_created(sender, **kwargs):
Node.refresh_nodes()
with tmp_to_root_org():
Node.refresh_nodes()
@receiver(post_save, sender=AuthBook)
def on_authbook_created(sender, instance=None, created=True, **kwargs):
if created and instance:
instance.set_version()

View File

@ -232,7 +232,8 @@ FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755
# Cache use redis
CACHES = {
'default': {
'BACKEND': 'redis_cache.RedisCache',
# 'BACKEND': 'redis_cache.RedisCache',
'BACKEND': 'redis_lock.django_cache.RedisCache',
'LOCATION': 'redis://:%(password)s@%(host)s:%(port)s/%(db)s' % {
'password': CONFIG.REDIS_PASSWORD,
'host': CONFIG.REDIS_HOST,

View File

@ -278,7 +278,7 @@ class AdHocExecution(OrgModelMixin):
raw = ''
try:
date_start_s = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
date_start_s = timezone.now().now().strftime('%Y-%m-%d %H:%M:%S')
print(_("{} Start task: {}").format(date_start_s, self.task.name))
raw, summary = self.start_runner()
except Exception as e:
@ -286,7 +286,7 @@ class AdHocExecution(OrgModelMixin):
raw = {"dark": {"all": str(e)}, "contacted": []}
finally:
self.clean_up(summary, time_start)
date_end = timezone.now()
date_end = timezone.now().now()
date_end_s = date_end.strftime('%Y-%m-%d %H:%M:%S')
print(_("{} Task finish").format(date_end_s))
print('.\n\n.')

View File

@ -96,3 +96,5 @@ django-cas-ng==4.0.1
python-cas==1.5.0
ipython
huaweicloud-sdk-python==1.0.21
django-redis==4.11.0
python-redis-lock==3.5.0