diff --git a/apps/assets/api.py b/apps/assets/api.py
index ab3507b3d..860f7111c 100644
--- a/apps/assets/api.py
+++ b/apps/assets/api.py
@@ -18,14 +18,16 @@ from rest_framework.response import Response
from rest_framework_bulk import BulkModelViewSet
from rest_framework_bulk import ListBulkCreateUpdateDestroyAPIView
from django.shortcuts import get_object_or_404
+from django.db.models import Q
from common.mixins import IDInFilterMixin
-from common.utils import get_object_or_none
from .hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser, \
- get_user_granted_assets, push_users
+ get_user_granted_assets
from .models import AssetGroup, Asset, Cluster, SystemUser, AdminUser
from . import serializers
-from .tasks import update_assets_hardware_info, test_admin_user_connectability_manual
+from .tasks import update_assets_hardware_info, test_admin_user_connectability, \
+ test_admin_user_connectability_manual, push_system_user_to_cluster_assets, \
+ test_system_user_connectability
class AssetViewSet(IDInFilterMixin, BulkModelViewSet):
@@ -51,8 +53,9 @@ class AssetViewSet(IDInFilterMixin, BulkModelViewSet):
queryset = queryset.filter(groups__id=asset_group_id)
if admin_user_id:
admin_user = get_object_or_404(AdminUser, id=admin_user_id)
+ assets_direct = [asset.id for asset in admin_user.asset_set.all()]
clusters = [cluster.id for cluster in admin_user.cluster_set.all()]
- queryset = queryset.filter(cluster__id__in=clusters)
+ queryset = queryset.filter(Q(cluster__id__in=clusters)|Q(id__in=assets_direct))
return queryset
@@ -65,15 +68,6 @@ class AssetGroupViewSet(IDInFilterMixin, BulkModelViewSet):
permission_classes = (IsSuperUser,)
-class AssetUpdateGroupApi(generics.RetrieveUpdateAPIView):
- """
- Asset update it's group api
- """
- queryset = Asset.objects.all()
- serializer_class = serializers.AssetUpdateGroupSerializer
- permission_classes = (IsSuperUser,)
-
-
class GroupUpdateAssetsApi(generics.RetrieveUpdateAPIView):
"""
Asset group, update it's asset member
@@ -117,6 +111,18 @@ class ClusterViewSet(IDInFilterMixin, BulkModelViewSet):
permission_classes = (IsSuperUser,)
+# TOdo
+class ClusterTestAssetsAliveApi(generics.RetrieveAPIView):
+ """
+ Test cluster asset can connect using admin user or not
+ """
+ queryset = Cluster.objects.all()
+ permission_classes = (IsSuperUser,)
+
+ def retrieve(self, request, *args, **kwargs):
+ cluster = self.get_object()
+
+
class ClusterAddAssetsApi(generics.UpdateAPIView):
queryset = Cluster.objects.all()
serializer_class = serializers.ClusterUpdateAssetsSerializer
@@ -162,7 +168,7 @@ class AdminUserAddClustersApi(generics.UpdateAPIView):
return Response({'error': serializer.errors}, status=400)
-class SystemUserViewSet(IDInFilterMixin, BulkModelViewSet):
+class SystemUserViewSet(BulkModelViewSet):
"""
System user api set, for add,delete,update,list,retrieve resource
"""
@@ -170,6 +176,10 @@ class SystemUserViewSet(IDInFilterMixin, BulkModelViewSet):
serializer_class = serializers.SystemUserSerializer
permission_classes = (IsSuperUserOrAppUser,)
+ def update(self, request, *args, **kwargs):
+ print(request.data)
+ return super().update(request, *args, **kwargs)
+
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
"""
@@ -199,7 +209,7 @@ class SystemUserAuthInfoApi(generics.RetrieveAPIView):
return Response(data)
-class AssetRefreshHardwareView(generics.RetrieveAPIView):
+class AssetRefreshHardwareApi(generics.RetrieveAPIView):
"""
Refresh asset hardware info
"""
@@ -217,7 +227,7 @@ class AssetRefreshHardwareView(generics.RetrieveAPIView):
return Response({"msg": "ok"})
-class AssetAdminUserTestView(AssetRefreshHardwareView):
+class AssetAdminUserTestApi(generics.RetrieveAPIView):
"""
Test asset admin user connectivity
"""
@@ -227,9 +237,47 @@ class AssetAdminUserTestView(AssetRefreshHardwareView):
def retrieve(self, request, *args, **kwargs):
asset_id = kwargs.get('pk')
asset = get_object_or_404(Asset, pk=asset_id)
- result = test_admin_user_connectability_manual(asset)
- if result:
- return Response('1')
+ ok, msg = test_admin_user_connectability_manual(asset)
+ if ok:
+ return Response({"msg": "pong"})
else:
- return Response('0', status=502)
+ return Response({"error": msg}, status=502)
+
+class AdminUserTestConnectiveApi(generics.RetrieveAPIView):
+ """
+ Test asset admin user connectivity
+ """
+ queryset = AdminUser.objects.all()
+ permission_classes = (IsSuperUser,)
+
+ def retrieve(self, request, *args, **kwargs):
+ admin_user = self.get_object()
+ test_admin_user_connectability.delay(admin_user, force=True)
+ return Response({"msg": "Task created"})
+
+
+class SystemUserPushApi(generics.RetrieveAPIView):
+ """
+ Push system user to cluster assets api
+ """
+ queryset = SystemUser.objects.all()
+ permission_classes = (IsSuperUser,)
+
+ def retrieve(self, request, *args, **kwargs):
+ system_user = self.get_object()
+ push_system_user_to_cluster_assets.delay(system_user, force=True)
+ return Response({"msg": "Task created"})
+
+
+class SystemUserTestConnectiveApi(generics.RetrieveAPIView):
+ """
+ Push system user to cluster assets api
+ """
+ queryset = SystemUser.objects.all()
+ permission_classes = (IsSuperUser,)
+
+ def retrieve(self, request, *args, **kwargs):
+ system_user = self.get_object()
+ test_system_user_connectability.delay(system_user, force=True)
+ return Response({"msg": "Task created"})
diff --git a/apps/assets/forms.py b/apps/assets/forms.py
index 2b701dcec..2bf6df507 100644
--- a/apps/assets/forms.py
+++ b/apps/assets/forms.py
@@ -273,26 +273,24 @@ class SystemUserForm(forms.ModelForm):
}
-class SystemUserUpdateForm(forms.ModelForm):
- class Meta:
- model = SystemUser
- fields = [
- 'name', 'username', 'protocol', 'priority',
- 'sudo', 'comment', 'shell', 'cluster'
- ]
- widgets = {
- 'name': forms.TextInput(attrs={'placeholder': _('Name')}),
- 'username': forms.TextInput(attrs={'placeholder': _('Username')}),
- 'cluster': forms.SelectMultiple(
- attrs={'class': 'select2',
- 'data-placeholder': _(' Select clusters')}),
- }
- help_texts = {
- 'name': '* required',
- 'username': '* required',
- 'cluster': 'If auto push checked, then push system user to that cluster assets',
- 'priority': 'High level will be using login asset as default, if user was granted more than 2 system user',
- }
+class SystemUserUpdateForm(SystemUserForm):
+ def save(self, commit=True):
+ # Because we define custom field, so we need rewrite :method: `save`
+ password = self.cleaned_data.get('password', None)
+ private_key_file = self.cleaned_data.get('private_key_file')
+ system_user = super(forms.ModelForm, self).save()
+
+ if private_key_file:
+ print(private_key_file)
+ private_key = private_key_file.read().strip().decode('utf-8')
+ public_key = ssh_pubkey_gen(private_key=private_key)
+ else:
+ private_key = public_key = None
+ system_user.set_auth(password=password, private_key=private_key, public_key=public_key)
+ return system_user
+
+ def clean_password(self):
+ return self.cleaned_data['password']
class SystemUserAuthForm(forms.Form):
diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py
index f606870de..905cee012 100644
--- a/apps/assets/models/asset.py
+++ b/apps/assets/models/asset.py
@@ -116,6 +116,23 @@ class Asset(models.Model):
else:
return False
+ @property
+ def admin_user_avail(self):
+ if self.admin_user:
+ admin_user = self.admin_user
+ elif self.cluster and self.cluster.admin_user:
+ admin_user = self.cluster.admin_user
+ else:
+ return None
+ return admin_user
+
+ @property
+ def is_has_private_admin_user(self):
+ if self.admin_user:
+ return True
+ else:
+ return False
+
def to_json(self):
return {
'id': self.id,
@@ -133,12 +150,8 @@ class Asset(models.Model):
Todo: May be move to ops implements it
"""
data = self.to_json()
- admin_user = None
- if self.admin_user:
- admin_user = self.admin_user
- elif self.cluster and self.cluster.admin_user:
- admin_user = self.cluster.admin_user
- if admin_user:
+ if self.admin_user_avail:
+ admin_user = self.admin_user_avail
data.update({
'username': admin_user.username,
'password': admin_user.password,
diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py
index 03fcf3068..c9db83e27 100644
--- a/apps/assets/models/user.py
+++ b/apps/assets/models/user.py
@@ -8,12 +8,14 @@ import uuid
from hashlib import md5
import sshpubkeys
+from django.core.cache import cache
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from common.utils import signer, ssh_key_string_to_obj, ssh_key_gen
from .utils import private_key_validator
+from ..const import SYSTEM_USER_CONN_CACHE_KEY
__all__ = ['AdminUser', 'SystemUser',]
@@ -103,6 +105,7 @@ class AssetUser(models.Model):
update_fields.append('_public_key')
if update_fields:
+ print(update_fields)
self.save(update_fields=update_fields)
def auto_gen_auth(self):
@@ -195,7 +198,7 @@ class SystemUser(AssetUser):
('P', 'Password'),
('K', 'Public key'),
)
- cluster = models.ManyToManyField('assets.Cluster', verbose_name=_("Cluster"))
+ cluster = models.ManyToManyField('assets.Cluster', null=True, blank=True, verbose_name=_("Cluster"))
priority = models.IntegerField(default=10, verbose_name=_("Priority")) # Todo: If user granted more priority user, default will be login as the hign
protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol'))
auto_push = models.BooleanField(default=True, verbose_name=_('Auto push'))
@@ -224,6 +227,19 @@ class SystemUser(AssetUser):
'auto_push': self.auto_push,
}
+ @property
+ def assets_connective(self):
+ _result = cache.get(SYSTEM_USER_CONN_CACHE_KEY.format(self.name), {})
+ return _result
+
+ @property
+ def unreachable_assets(self):
+ return list(self.assets_connective.get('dark', {}).keys())
+
+ @property
+ def reachable_assets(self):
+ return self.assets_connective.get('contacted', [])
+
class Meta:
ordering = ['name']
diff --git a/apps/assets/serializers.py b/apps/assets/serializers.py
index be54089cb..f13f7837d 100644
--- a/apps/assets/serializers.py
+++ b/apps/assets/serializers.py
@@ -25,17 +25,6 @@ class AssetGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer):
return obj.assets.count()
-class AssetUpdateGroupSerializer(serializers.ModelSerializer):
- """
- 资产更新自己所在资产组的请求数据结构定义
- """
- groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all())
-
- class Meta:
- model = Asset
- fields = ['id', 'groups']
-
-
class AssetUpdateSystemUserSerializer(serializers.ModelSerializer):
"""
资产更新其系统用户请求的数据结构定义
@@ -90,11 +79,7 @@ class AdminUserSerializer(serializers.ModelSerializer):
@staticmethod
def get_assets_amount(obj):
- amount = 0
- clusters = obj.cluster_set.all()
- for cluster in clusters:
- amount += len(cluster.assets.all())
- return amount
+ return obj.assets_amount
class SystemUserSerializer(serializers.ModelSerializer):
@@ -102,6 +87,9 @@ class SystemUserSerializer(serializers.ModelSerializer):
系统用户
"""
unreachable_amount = serializers.SerializerMethodField()
+ reachable_amount = serializers.SerializerMethodField()
+ unreachable_assets = serializers.SerializerMethodField()
+ reachable_assets = serializers.SerializerMethodField()
assets_amount = serializers.SerializerMethodField()
class Meta:
@@ -109,12 +97,18 @@ class SystemUserSerializer(serializers.ModelSerializer):
exclude = ('_password', '_private_key', '_public_key')
@staticmethod
- def get_unreachable_amount(obj):
- data = cache.get(SYSTEM_USER_CONN_CACHE_KEY.format(obj.name))
- if data:
- return len(data.get('dark'))
- else:
- return "Unknown"
+ def get_unreachable_assets(obj):
+ return obj.unreachable_assets
+
+ @staticmethod
+ def get_reachable_assets(obj):
+ return obj.reachable_assets
+
+ def get_unreachable_amount(self, obj):
+ return len(self.get_unreachable_assets(obj))
+
+ def get_reachable_amount(self, obj):
+ return len(self.get_reachable_assets(obj))
@staticmethod
def get_assets_amount(obj):
diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py
index 3370470df..09430da96 100644
--- a/apps/assets/tasks.py
+++ b/apps/assets/tasks.py
@@ -181,10 +181,10 @@ def test_admin_user_connectability_manual(asset, task_name=None):
if result.results_summary['dark']:
cache.set(const.ASSET_ADMIN_CONN_CACHE_KEY.format(asset.hostname), 0, CACHE_MAX_TIME)
- return False
+ return False, result.results_summary['dark']
else:
cache.set(const.ASSET_ADMIN_CONN_CACHE_KEY.format(asset.hostname), 1, CACHE_MAX_TIME)
- return True
+ return True, ""
@shared_task
@@ -211,7 +211,8 @@ def test_system_user_connectability(system_user, force=False):
)
cache.set(lock_key, 1, CACHE_MAX_TIME)
result = task.run()
- cache_key = const.SYSTEM_USER_CONN_CACHE_KEY
+ cache_key = const.SYSTEM_USER_CONN_CACHE_KEY.format(system_user.name)
+ print("Set cache: {} {}".format(cache_key, result.results_summary))
cache.set(cache_key, result.results_summary, CACHE_MAX_TIME)
return result.results_summary
@@ -369,7 +370,7 @@ def update_asset_info_when_created(sender, instance=None, created=False, **kwarg
@receiver(post_save, sender=Asset, dispatch_uid="my_unique_identifier")
-def update_asset_conn_info_when_created(sender, instance=None, created=False, **kwargs):
+def update_asset_conn_info_on_created(sender, instance=None, created=False, **kwargs):
if instance and created:
task_name = 'TEST-ASSET-CONN-WHEN-CREATED-{}'.format(instance)
msg = "Receive asset {} create signal, test asset connectability".format(
@@ -380,7 +381,7 @@ def update_asset_conn_info_when_created(sender, instance=None, created=False, **
@receiver(post_save, sender=Asset, dispatch_uid="my_unique_identifier")
-def push_system_user_when_created(sender, instance=None, created=False, **kwargs):
+def push_system_user_on_created(sender, instance=None, created=False, **kwargs):
if instance and created:
task_name = 'PUSH-SYSTEM-USER-WHEN-ASSET-CREATED-{}'.format(instance)
system_users = instance.cluster.systemuser_set.all()
@@ -392,15 +393,7 @@ def push_system_user_when_created(sender, instance=None, created=False, **kwargs
@receiver(post_save, sender=SystemUser)
-def push_system_user_on_change(sender, instance=None, created=False, **kwargs):
- if instance and instance.auto_push:
- logger.debug("System user `{}` auth changed, push it".format(instance.name))
- task_name = "PUSH-SYSTEM-USER-ON-CREATED-{}".format(instance.name)
- push_system_user_to_cluster_assets.delay(instance, task_name)
-
-
-@receiver(post_save, sender=SystemUser)
-def push_system_user_on_change(sender, instance=None, update_fields=None, **kwargs):
+def push_system_user_on_auth_change(sender, instance=None, update_fields=None, **kwargs):
fields_check = {'_password', '_private_key', '_public_key'}
auth_changed = update_fields & fields_check if update_fields else None
if instance and instance.auto_push and auth_changed:
diff --git a/apps/assets/templates/assets/admin_user_assets.html b/apps/assets/templates/assets/admin_user_assets.html
index b1698c976..4b0429605 100644
--- a/apps/assets/templates/assets/admin_user_assets.html
+++ b/apps/assets/templates/assets/admin_user_assets.html
@@ -60,7 +60,7 @@
{% trans 'IP' %} |
{% trans 'Port' %} |
{% trans 'Type' %} |
- {% trans 'Valid' %} |
+ {% trans 'Alive' %} |
@@ -78,10 +78,10 @@
- {% trans 'Retest connectivity' %}: |
+ {% trans 'Test connective' %}: |
-
+
|
@@ -98,56 +98,6 @@
{% endblock %}
{% block custom_foot_js %}
{% endblock %}
diff --git a/apps/assets/templates/assets/admin_user_detail.html b/apps/assets/templates/assets/admin_user_detail.html
index 5f0646197..577f16402 100644
--- a/apps/assets/templates/assets/admin_user_detail.html
+++ b/apps/assets/templates/assets/admin_user_detail.html
@@ -31,7 +31,7 @@
-
+
{{ admin_user.name }}
@@ -77,26 +77,8 @@
-
-
-
- {% trans 'Quick update' %}
-
-
-
-
-
- {% trans 'Test auth all assets manual' %}: |
-
-
-
-
- |
-
-
-
-
-
+
+
{% trans 'Using this as cluster admin user' %}
diff --git a/apps/assets/templates/assets/asset_detail.html b/apps/assets/templates/assets/asset_detail.html
index 44e5bb547..080f701f8 100644
--- a/apps/assets/templates/assets/asset_detail.html
+++ b/apps/assets/templates/assets/asset_detail.html
@@ -71,8 +71,8 @@
{% trans 'Admin user' %}: |
- {% if asset.admin_user %}
- {{ asset.admin_user.name }} |
+ {% if asset.admin_user_avail %}
+ {{ asset.admin_user_avail.name }} |
{% else %}
None |
{% endif %}
@@ -195,6 +195,14 @@
+
+ {% trans 'Test is alive' %}: |
+
+
+
+
+ |
+
@@ -248,7 +256,7 @@
diff --git a/apps/assets/templates/assets/cluster_assets.html b/apps/assets/templates/assets/cluster_assets.html
index 16a3909b0..13d779d8f 100644
--- a/apps/assets/templates/assets/cluster_assets.html
+++ b/apps/assets/templates/assets/cluster_assets.html
@@ -64,6 +64,25 @@
+
+ {% trans 'Quick update' %}
+
+
+
+
+
+ {% trans 'Test assets alive' %}: |
+
+
+
+
+ |
+
+
+
+
+
+
{% trans 'Add assets to' %} {{ cluster.name }}
@@ -173,7 +192,6 @@ $(document).ready(function () {
});
initTable();
})
-
.on('click', '.btn-add-assets', function () {
if (Object.keys(jumpserver.assets_selected).length === 0) {
return false;
@@ -185,5 +203,8 @@ $(document).ready(function () {
addAssets(assets_id);
})
+.on('click', '#btn-test-assets', function () {
+ console.log('ok');
+})
{% endblock %}
diff --git a/apps/assets/templates/assets/cluster_detail.html b/apps/assets/templates/assets/cluster_detail.html
index 19ab7c927..cd2ecd25e 100644
--- a/apps/assets/templates/assets/cluster_detail.html
+++ b/apps/assets/templates/assets/cluster_detail.html
@@ -102,6 +102,44 @@
+{# #}
+{#
#}
+{#
#}
+{# {% trans 'Update admin user' %}#}
+{#
#}
+{#
#}
+{#
#}
+{# #}
+{# #}
+{##}
+{# {% for cluster in system_user.cluster.all %}#}
+{# #}
+{# {{ cluster.name }} | #}
+{# #}
+{# #}
+{# | #}
+{#
#}
+{# {% endfor %}#}
+{# #}
+{#
#}
+{#
#}
+{#
#}
+{#
#}
@@ -111,46 +149,16 @@
{% endblock %}
{% block custom_foot_js %}
{% endblock %}
diff --git a/apps/assets/templates/assets/system_user_asset.html b/apps/assets/templates/assets/system_user_asset.html
index edda1c222..75e1b264d 100644
--- a/apps/assets/templates/assets/system_user_asset.html
+++ b/apps/assets/templates/assets/system_user_asset.html
@@ -16,11 +16,6 @@
{% trans 'Detail' %}
-
-
- {% trans 'Auth' %}
-
-
{% trans 'Assets' %}
@@ -78,15 +73,15 @@
{% trans 'Push system user manually' %}: |
-
+
|
- {% trans 'Refresh assets connectivity' %}: |
+ {% trans 'Test assets connective' %}: |
-
+
|
@@ -103,26 +98,8 @@
{% endblock %}
{% block custom_foot_js %}
+ // clear jumpserver.groups_selected
+ jumpserver.cluster_selected = {};
+ };
+ APIUpdateAttr({
+ url: the_url,
+ body: JSON.stringify(body),
+ success: success
+ });
+}
+jumpserver.cluster_selected = {};
+$(document).ready(function () {
+ $('.select2').select2()
+ .on('select2:select', function(evt) {
+ var data = evt.params.data;
+ jumpserver.cluster_selected[data.id] = data.text;
+ })
+ .on('select2:unselect', function(evt) {
+ var data = evt.params.data;
+ delete jumpserver.cluster_selected[data.id];
+ });
+})
+.on('click', '#btn-auto-push', function () {
+ var checked = $(this).prop('checked');
+ var the_url = "{% url 'api-assets:system-user-detail' pk=system_user.id %}";
+ var body = {
+ 'auto_push': checked
+ };
+ APIUpdateAttr({
+ url: the_url,
+ body: JSON.stringify(body)
+ });
+})
+.on('click', '#btn-add-to-cluster', function() {
+ if (Object.keys(jumpserver.cluster_selected).length === 0) {
+ return false;
+ }
+ var clusters = $('.bdg_cluster').map(function() {
+ return $(this).data('gid');
+ }).get();
+ $.map(jumpserver.cluster_selected, function(value, index) {
+ clusters.push(index);
+ });
+ updateSystemUserCluster(clusters);
+})
+.on('click', '.btn-remove-from-cluster', function() {
+ var $this = $(this);
+ var $tr = $this.closest('tr');
+ var $badge = $tr.find('.bdg_cluster');
+ var gid = $badge.data('gid');
+ var cluster_name = $badge.html() || $badge.text();
+ $('#groups_selected').append(
+ ''
+ );
+ $tr.remove();
+ var clusters = $('.bdg_cluster').map(function () {
+ return $(this).data('gid');
+ }).get();
+ updateSystemUserCluster(clusters);
+})
+
{% endblock %}
diff --git a/apps/assets/templates/assets/system_user_list.html b/apps/assets/templates/assets/system_user_list.html
index 6aa32a622..c200b9250 100644
--- a/apps/assets/templates/assets/system_user_list.html
+++ b/apps/assets/templates/assets/system_user_list.html
@@ -17,7 +17,9 @@
{% trans 'Name' %} |
{% trans 'Username' %} |
{% trans 'Asset' %} |
+ {% trans 'Reachable' %} |
{% trans 'Unreachable' %} |
+ {% trans 'Ratio' %} |
{% trans 'Comment' %} |
{% trans 'Action' %} |
@@ -25,19 +27,6 @@
-
{% endblock %}
{% block custom_foot_js %}