diff --git a/apps/assets/forms.py b/apps/assets/forms.py index e41044f16..9b0df2580 100644 --- a/apps/assets/forms.py +++ b/apps/assets/forms.py @@ -224,13 +224,16 @@ class SystemUserForm(forms.ModelForm): password = self.cleaned_data.get('password', None) private_key_file = self.cleaned_data.get('private_key_file') auto_generate_key = self.cleaned_data.get('auto_generate_key') + private_key = None + public_key = None if auto_generate_key: logger.info('Auto set system user auth') system_user.auto_gen_auth() else: - private_key = private_key_file.read().strip().decode('utf-8') - public_key = ssh_pubkey_gen(private_key=private_key) + if private_key_file: + private_key = private_key_file.read().strip().decode('utf-8') + public_key = ssh_pubkey_gen(private_key=private_key) system_user.set_auth(password=password, private_key=private_key, public_key=public_key) return system_user diff --git a/apps/assets/templates/assets/user_asset_list.html b/apps/assets/templates/assets/user_asset_list.html index 4278ffa4e..2f71320d1 100644 --- a/apps/assets/templates/assets/user_asset_list.html +++ b/apps/assets/templates/assets/user_asset_list.html @@ -34,6 +34,7 @@ {% trans 'Hardware' %} {% trans 'Active' %} {% trans 'Connective' %} + {% trans 'Action' %} @@ -70,12 +71,18 @@ function initTable() { } else { $(td).html('') } + }}, + {targets: 9, createdCell: function (td, cellData, rowData) { + var conn_btn = '{% trans "Connect" %}'.replace("{{ DEFAULT_PK }}", cellData); + $(td).html(conn_btn) }} ], ajax_url: '{% url "api-assets:asset-list" %}', - columns: [{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" }, + columns: [ + {data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" }, {data: "get_type_display" }, {data: "get_env_display"}, {data: "hardware_info"}, - {data: "is_active" }, {data: "is_connective"}], + {data: "is_active" }, {data: "is_connective"}, {data: "id"} + ], op_html: $('#actions').html() }; return jumpserver.initDataTable(options); diff --git a/apps/terminal/urls/views_urls.py b/apps/terminal/urls/views_urls.py index ad3ecf4f9..834d0f39d 100644 --- a/apps/terminal/urls/views_urls.py +++ b/apps/terminal/urls/views_urls.py @@ -15,6 +15,7 @@ urlpatterns = [ url(r'^terminal/(?P[0-9a-zA-Z\-]{36})/connect/$', views.TerminalConnectView.as_view(), name='terminal-connect'), url(r'^terminal/(?P[0-9a-zA-Z\-]{36})/update/$', views.TerminalUpdateView.as_view(), name='terminal-update'), url(r'^(?P[0-9a-zA-Z\-]{36})/accept/$', views.TerminalAcceptView.as_view(), name='terminal-accept'), + url(r'^web-terminal/$', views.WebTerminalView.as_view(), name='web-terminal'), # Session view url(r'^session-online/$', views.SessionOnlineListView.as_view(), name='session-online-list'), diff --git a/apps/terminal/utils.py b/apps/terminal/utils.py index e81ea0e3b..1f3422e0a 100644 --- a/apps/terminal/utils.py +++ b/apps/terminal/utils.py @@ -18,8 +18,6 @@ def get_session_system_user_list(): return set(list(Session.objects.values_list('system_user', flat=True))) - - def get_user_list_from_cache(): return cache.get(USERS_CACHE_KEY) diff --git a/apps/terminal/views/terminal.py b/apps/terminal/views/terminal.py index 30d16a1e2..2afa882bf 100644 --- a/apps/terminal/views/terminal.py +++ b/apps/terminal/views/terminal.py @@ -1,10 +1,10 @@ # ~*~ coding: utf-8 ~*~ # - from django.views.generic import ListView, UpdateView, DeleteView, \ - DetailView, TemplateView + DetailView, View from django.contrib.auth.mixins import LoginRequiredMixin from django.utils.translation import ugettext as _ +from django.shortcuts import redirect from django.urls import reverse_lazy, reverse from common.mixins import JSONResponseMixin @@ -16,6 +16,7 @@ from ..hands import AdminUserRequiredMixin __all__ = [ "TerminalListView", "TerminalUpdateView", "TerminalDetailView", "TerminalDeleteView", "TerminalConnectView", "TerminalAcceptView", + "WebTerminalView", ] @@ -115,3 +116,8 @@ class TerminalConnectView(LoginRequiredMixin, DetailView): kwargs.update(context) return super(TerminalConnectView, self).get_context_data(**kwargs) + + +class WebTerminalView(LoginRequiredMixin, View): + def get(self, request, *args, **kwargs): + return redirect('/luna/?' + request.GET.urlencode()) diff --git a/run_server.py b/run_server.py index 49e064e47..fe11bea94 100644 --- a/run_server.py +++ b/run_server.py @@ -6,6 +6,7 @@ import threading import time import argparse import platform +import sys from apps import __version__ @@ -27,6 +28,7 @@ EXIT_EVENT = threading.Event() EXIT_MSGS = [] + try: os.makedirs(os.path.join(BASE_DIR, "data", "static")) os.makedirs(os.path.join(BASE_DIR, "data", "media")) @@ -54,9 +56,8 @@ def start_gunicorn(): cmd = "gunicorn jumpserver.wsgi -b {}:{} -w {}".format(HTTP_HOST, HTTP_PORT, WORKERS) if DEBUG: cmd += " --reload" - subprocess.call(cmd, shell=True) - EXIT_MSGS.append("Gunicorn start failed") - EXIT_EVENT.set() + p = subprocess.Popen(cmd, shell=True, stdout=sys.stdout, stderr=sys.stderr) + return p def start_celery(): @@ -68,16 +69,15 @@ def start_celery(): if platform.platform().startswith("Linux"): cmd = """ id jumpserver || useradd -s /sbin/nologin jumpserver; - su jumpserver -c 'celery -A common worker -l {}' + su jumpserver -c 'celery -A common worker -l {}'; """.format(LOG_LEVEL.lower()) else: cmd = """ - export C_FORCE_ROOT=1;celery -A common worker -l {}' + export C_FORCE_ROOT=1;celery -A common worker -l {} """.format(LOG_LEVEL.lower()) - subprocess.call(cmd, shell=True) - EXIT_MSGS.append("Celery start failed") - EXIT_EVENT.set() + p = subprocess.Popen(cmd, shell=True, stdout=sys.stdout, stderr=sys.stderr) + return p def start_beat(): @@ -86,40 +86,44 @@ def start_beat(): os.environ.setdefault('PYTHONOPTIMIZE', '1') os.environ.setdefault('C_FORCE_ROOT', '1') scheduler = "django_celery_beat.schedulers:DatabaseScheduler" - cmd = 'celery -A common beat -l {} --scheduler {} --max-interval 5 '.format(LOG_LEVEL, scheduler) - subprocess.call(cmd, shell=True) - EXIT_MSGS.append("Beat start failed") - EXIT_EVENT.set() + cmd = 'celery -A common beat -l {} --scheduler {} --max-interval 60 '.format(LOG_LEVEL, scheduler) + p = subprocess.Popen(cmd, shell=True, stdout=sys.stdout, stderr=sys.stderr) + return p def start_service(services): - make_migrations() - print(time.ctime()) print('Jumpserver version {}, more see https://www.jumpserver.org'.format( __version__)) print('Quit the server with CONTROL-C.') - threads = [] - if 'gunicorn' in args.services: - threads.append(threading.Thread(target=start_gunicorn, args=())) - if 'celery' in args.services: - threads.append(threading.Thread(target=start_celery, args=())) - if 'beat' in args.services: - threads.append(threading.Thread(target=start_beat, args=())) - if 'all' in args.services: - _threads = [] - for func in (start_gunicorn, start_celery, start_beat): - t = threading.Thread(target=func, args=()) - _threads.append(t) - threads = _threads + processes = {} + services_all = { + "gunicorn": start_gunicorn, + "celery": start_celery, + "beat": start_beat + } - for t in threads: - t.start() + if 'all' in services: + for name, func in services_all.items(): + processes[name] = func() + else: + for name in services: + func = services_all.get(name) + processes[name] = func() - if EXIT_EVENT.wait(): - print("\n\n" + "####" * 30) - print("\n".join(EXIT_MSGS)) + stop_event = threading.Event() + while not stop_event.is_set(): + for name, proc in processes.items(): + if proc.poll() is not None: + print("\n\n" + "####"*10 + " ERROR OCCUR " + "####"*10) + print("Start service {} [FAILED]".format(name)) + for _, p in processes.items(): + p.terminate() + stop_event.set() + print("Exited".format(name)) + break + time.sleep(5) if __name__ == '__main__':