diff --git a/apps/assets/api.py b/apps/assets/api.py index 334a7842e..aadebbd93 100644 --- a/apps/assets/api.py +++ b/apps/assets/api.py @@ -12,10 +12,12 @@ from django.shortcuts import get_object_or_404 from common.mixins import IDInFilterMixin from common.utils import get_object_or_none, signer -from .hands import IsSuperUser, IsAppUser, IsValidUser, get_user_granted_assets +from .hands import IsSuperUser, IsAppUser, IsValidUser, \ + get_user_granted_assets, push_users from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser from . import serializers from .tasks import update_assets_hardware_info +from .utils import test_admin_user_connective_manual class AssetViewSet(IDInFilterMixin, BulkModelViewSet): @@ -97,6 +99,16 @@ class SystemUserUpdateApi(generics.RetrieveUpdateAPIView): serializer_class = serializers.AssetUpdateSystemUserSerializer permission_classes = (IsSuperUser,) + def patch(self, request, *args, **kwargs): + asset = self.get_object() + old_system_users = set(asset.system_users.all()) + response = super(SystemUserUpdateApi, self).patch(request, *args, **kwargs) + system_users_new = set(asset.system_users.all()) + system_users = system_users_new - old_system_users + system_users = [system_user._to_secret_json() for system_user in system_users] + push_users.delay([asset], system_users) + return response + class SystemUserUpdateAssetsApi(generics.RetrieveUpdateAPIView): queryset = SystemUser.objects.all() @@ -110,19 +122,6 @@ class SystemUserUpdateAssetGroupApi(generics.RetrieveUpdateAPIView): permission_classes = (IsSuperUser,) -# class IDCAssetsApi(generics.ListAPIView): -# model = IDC -# serializer_class = serializers.AssetSerializer -# -# def get(self, request, *args, **kwargs): -# filter_kwargs = {self.lookup_field: self.kwargs[self.lookup_field]} -# self.object = get_object_or_404(self.model, **filter_kwargs) -# return super(IDCAssetsApi, self).get(request, *args, **kwargs) -# -# def get_queryset(self): -# return self.object.assets.all() - - class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView): queryset = Asset.objects.all() serializer_class = serializers.AssetSerializer @@ -154,5 +153,22 @@ class AssetRefreshHardwareView(generics.RetrieveAPIView): def retrieve(self, request, *args, **kwargs): asset_id = kwargs.get('pk') asset = get_object_or_404(Asset, pk=asset_id) - update_assets_hardware_info([asset]) - return super(AssetRefreshHardwareView, self).retrieve(request, *args, **kwargs) + summary = update_assets_hardware_info([asset]) + if len(summary['failed']) == 0: + return super(AssetRefreshHardwareView, self).retrieve(request, *args, **kwargs) + else: + return Response('', status=502) + + +class AssetAdminUserTestView(AssetRefreshHardwareView): + queryset = Asset.objects.all() + permission_classes = (IsSuperUser,) + + def retrieve(self, request, *args, **kwargs): + asset_id = kwargs.get('pk') + asset = get_object_or_404(Asset, pk=asset_id) + result = test_admin_user_connective_manual([asset]) + if result: + return Response('1') + else: + return Response('0', status=502) diff --git a/apps/assets/hands.py b/apps/assets/hands.py index a504019e5..7d9986156 100644 --- a/apps/assets/hands.py +++ b/apps/assets/hands.py @@ -14,4 +14,5 @@ from users.utils import AdminUserRequiredMixin from users.permissions import IsAppUser, IsSuperUser, IsValidUser from users.models import User, UserGroup -from perms.utils import get_user_granted_assets \ No newline at end of file +from perms.utils import get_user_granted_assets +from perms.tasks import push_users \ No newline at end of file diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index 8a6d0bad6..02da386b0 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -76,7 +76,7 @@ class Asset(models.Model): platform = models.CharField(max_length=128, null=True, blank=True, verbose_name='Platform') os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS')) - os_version = models.FloatField(null=True, blank=True, verbose_name=_('OS Version')) + os_version = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('OS Version')) os_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=_('OS Arch')) hostname_raw = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hostname raw')) diff --git a/apps/assets/serializers.py b/apps/assets/serializers.py index 50e7188f3..615220948 100644 --- a/apps/assets/serializers.py +++ b/apps/assets/serializers.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- from django.utils.translation import ugettext_lazy as _ +from django.core.cache import cache from rest_framework import viewsets, serializers, generics from .models import AssetGroup, Asset, IDC, AdminUser, SystemUser from common.mixins import IDInFilterMixin @@ -117,6 +118,7 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): # system_users = SystemUserSerializer(many=True, read_only=True) # admin_user = AdminUserSerializer(many=False, read_only=True) hardware = serializers.SerializerMethodField() + is_online = serializers.SerializerMethodField() class Meta(object): model = Asset @@ -130,6 +132,16 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): else: return '' + @staticmethod + def get_is_online(obj): + hostname = obj.hostname + if cache.get(hostname) == '1': + return True + elif cache.get(hostname) == '0': + return False + else: + return 'Unknown' + def get_field_names(self, declared_fields, info): fields = super(AssetSerializer, self).get_field_names(declared_fields, info) fields.extend(['get_type_display', 'get_env_display']) diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py index 06cc2a9b4..68b0cafca 100644 --- a/apps/assets/tasks.py +++ b/apps/assets/tasks.py @@ -2,6 +2,8 @@ from celery import shared_task import json +from django.core.cache import cache + from ops.tasks import run_AdHoc from common.utils import get_object_or_none, capacity_convert, sum_capacity from .models import Asset @@ -43,7 +45,7 @@ def update_assets_hardware_info(assets): ___platform = info['ansible_system'] ___os = info['ansible_distribution'] - ___os_version = float(info['ansible_distribution_version']) + ___os_version = info['ansible_distribution_version'] ___os_arch = info['ansible_architecture'] ___hostname_raw = info['ansible_hostname'] @@ -51,24 +53,28 @@ def update_assets_hardware_info(assets): if k.startswith('___'): setattr(asset, k.strip('_'), v) asset.save() + return summary @shared_task -def test_admin_user_connective(assets=None): - if None: - assets = Asset.objects.filter(type__in=['Server', 'VM']) - if not assets: - return 'No asset get' +def update_assets_hardware_period(): + assets = Asset.objects.filter(type__in=['Server', 'VM']) + update_assets_hardware_info(assets) + + +@shared_task +def test_admin_user_connective_period(): + assets = Asset.objects.filter(type__in=['Server', 'VM']) task_tuple = ( ('ping', ''), ) - summary, result = run_AdHoc(task_tuple, assets, record=False) - return summary, result + summary, _ = run_AdHoc(task_tuple, assets, record=False) + for i in summary['success']: + cache.set(i, '1', 2*60*60*60) + + for i in summary['failed']: + cache.set(i, '0', 60*60*60) + return summary + -def get_assets_hardware_info(assets): - task_tuple = ( - ('setup', ''), - ) - task = run_AdHoc.delay(task_tuple, assets, record=False) - return task \ No newline at end of file diff --git a/apps/assets/templates/assets/asset_detail.html b/apps/assets/templates/assets/asset_detail.html index c56116d61..18ce868cc 100644 --- a/apps/assets/templates/assets/asset_detail.html +++ b/apps/assets/templates/assets/asset_detail.html @@ -188,7 +188,7 @@ {% trans 'Rrefresh hardware' %}: - + @@ -196,19 +196,10 @@ {% trans 'Test admin user' %}: - + - - {% trans 'Test system pingpong' %}: - - - - - - - @@ -453,8 +444,17 @@ $(document).ready(function () { var the_url = '{% url "api-assets:asset-detail" pk=99991937 %}'.replace('99991937', uid); var redirect_url = "{% url 'assets:asset-list' %}"; objectDelete($this, name, the_url, redirect_url); -}).on('click', '.btn-refresh-asset', function () { +}).on('click', '#btn_refresh_asset', function () { + alert('请等待几秒, 等待完成'); refreshAssetHardware() +}).on('click', '#btn_test_admin_user', function () { + $.ajax({ + url: '{% url "api-assets:asset-admin-user-test" pk=asset.id %}' + }).done(function (data, textStatue, jqXHR) { + toastr.success('Success') + }).fail(function (data, textStaue, errorThrown) { + toastr.error('Error') + }) }) diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index e47f48428..9bf9f122f 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -121,7 +121,9 @@ $(document).ready(function(){ } }}, {targets: 8, createdCell: function (td, cellData) { - if (!cellData) { + if (cellData == 'Unknown'){ + $(td).html('') + } else if (!cellData) { $(td).html('') } else { $(td).html('') @@ -136,7 +138,7 @@ $(document).ready(function(){ ajax_url: '{% url "api-assets:asset-list" %}', columns: [{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" }, {data: "get_type_display" }, {data: "get_env_display"}, {data: "hardware"}, - {data: "is_active" }, {data: "is_active"}, {data: "id" }], + {data: "is_active" }, {data: "is_online"}, {data: "id" }], op_html: $('#actions').html() }; var table = jumpserver.initDataTable(options); diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index ec1c8433c..f54b0a0e6 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -16,7 +16,6 @@ router.register(r'v1/system-user', api.SystemUserViewSet, 'system-user') urlpatterns = [ url(r'^v1/assets_bulk/$', api.AssetListUpdateApi.as_view(), name='asset-bulk-update'), - # url(r'^v1/idc/(?P[0-9]+)/assets/$', api.IDCAssetsApi.as_view(), name='api-idc-assets'), url(r'^v1/system-user/(?P[0-9]+)/auth-info/', api.SystemUserAuthInfoApi.as_view(), name='system-user-auth-info'), url(r'^v1/assets/(?P\d+)/groups/$', @@ -24,6 +23,8 @@ urlpatterns = [ url(r'^v1/assets/(?P\d+)/refresh/$', api.AssetRefreshHardwareView.as_view(), name='asset-refresh'), + url(r'^v1/assets/(?P\d+)/admin-user-test/$', + api.AssetAdminUserTestView.as_view(), name='asset-admin-user-test'), url(r'^v1/assets/(?P\d+)/system-users/$', api.SystemUserUpdateApi.as_view(), name='asset-update-system-users'), diff --git a/apps/assets/utils.py b/apps/assets/utils.py index cd064e942..e67412615 100644 --- a/apps/assets/utils.py +++ b/apps/assets/utils.py @@ -1,3 +1,17 @@ # ~*~ coding: utf-8 ~*~ # +from ops.utils import run_AdHoc + + +def test_admin_user_connective_manual(asset): + if not isinstance(asset, list): + asset = [asset] + task_tuple = ( + ('ping', ''), + ) + summary, _ = run_AdHoc(task_tuple, asset, record=False) + if len(summary['failed']) != 0: + return False + else: + return True diff --git a/apps/common/celery.py b/apps/common/celery.py index 51de45349..3094351e5 100644 --- a/apps/common/celery.py +++ b/apps/common/celery.py @@ -5,6 +5,7 @@ import os from datetime import timedelta from celery import Celery +from celery.schedules import crontab # set the default Django settings module for the 'celery' program. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'jumpserver.settings') @@ -19,3 +20,17 @@ app.config_from_object('django.conf:settings') app.autodiscover_tasks(lambda: [app_config.split('.')[0] for app_config in settings.INSTALLED_APPS]) +app.conf.update( + CELERYBEAT_SCHEDULE={ + 'refresh-asset-hardware-info': { + 'task': 'assets.tasks.update_assets_hardware_period', + 'schedule': 60*60*60*24, + 'args': (), + }, + 'test-admin-user-connective': { + 'task': 'assets.tasks.test_admin_user_connective_period', + 'schedule': 60*60*60, + 'args': (), + } + } +) diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index ed919cb47..7f8a6289b 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -108,6 +108,10 @@ TEMPLATES = [ LOGIN_REDIRECT_URL = reverse_lazy('index') LOGIN_URL = reverse_lazy('users:login') +SESSION_COOKIE_DOMAIN = CONFIG.SESSION_COOKIE_DOMAIN or None +CSRF_COOKIE_DOMAIN = CONFIG.CSRF_COOKIE_DOMAIN or None +SESSION_COOKIE_AGE = CONFIG.SESSION_COOKIE_AGE or 3600*24 + # Database # https://docs.djangoproject.com/en/1.10/ref/settings/#databases diff --git a/apps/ops/utils.py b/apps/ops/utils.py index 0c3cbbc99..b27c81671 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils.py @@ -27,7 +27,8 @@ def run_AdHoc(task_tuple, assets, :param pattern: :param record: :param verbose: - :return: + :return: summary: {'success': [], 'failed': [{'192.168.1.1': 'msg'}]} + result: {'contacted': {'hostname': [{''}, {''}], 'dark': []} """ if not assets: diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 2ad48ec86..c9b091338 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -149,7 +149,7 @@ function getCookie(name) { // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; + // break; } } } diff --git a/apps/users/views/login.py b/apps/users/views/login.py index fcbdac30c..115db0f1a 100644 --- a/apps/users/views/login.py +++ b/apps/users/views/login.py @@ -69,7 +69,7 @@ class UserLogoutView(TemplateView): def get(self, request, *args, **kwargs): auth_logout(request) - return super(UserLogoutView, self).get(request) + return super(UserLogoutView, self).get(request, *args, **kwargs) def get_context_data(self, **kwargs): context = { @@ -201,9 +201,4 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView): form = super(UserFirstLoginView, self).get_form(step, data, files) form.instance = self.request.user - if step is None: - step = self.steps.current - - # if step == '1': - # form.instance = self.request.user return form diff --git a/config_example.py b/config_example.py index cbe79aa8b..92a2bd43b 100644 --- a/config_example.py +++ b/config_example.py @@ -72,6 +72,11 @@ class Config: # Api token expiration when create TOKEN_EXPIRATION = 3600 + # Session and csrf domain settings + SESSION_COOKIE_DOMAIN = '.jms.com' + CSRF_COOKIE_DOMAIN = '.jms.com' + SESSION_COOKIE_AGE = 3600*24 + # Email SMTP setting, we only support smtp send mail # EMAIL_HOST = 'smtp.qq.com' # EMAIL_PORT = 25 diff --git a/requirements/rpm_requirements.txt b/requirements/rpm_requirements.txt index 3853d8419..03d5e2c92 100644 --- a/requirements/rpm_requirements.txt +++ b/requirements/rpm_requirements.txt @@ -1 +1 @@ -libtiff-devel libjpeg-devel libzip-devel freetype-devel lcms2-devel libwebp-devel tcl-devel tk-devel \ No newline at end of file +libtiff-devel libjpeg-devel libzip-devel freetype-devel lcms2-devel libwebp-devel tcl-devel tk-devel sshpass diff --git a/run_server.py b/run_server.py index 77cda4139..2af0a20ca 100644 --- a/run_server.py +++ b/run_server.py @@ -31,7 +31,7 @@ def start_celery(): os.environ.setdefault('C_FORCE_ROOT', '1') os.environ.setdefault('PYTHONOPTIMIZE', '1') print('start celery') - subprocess.call('celery -A common worker -s /tmp/celerybeat-schedule -l debug', shell=True) + subprocess.call('celery -A common worker -B -s /tmp/celerybeat-schedule -l debug', shell=True) def main():