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__':