diff --git a/apps/common/api.py b/apps/common/api.py
index e09cf972605bc8697a66f59e65f78f4ff1186495..193132b7a9fb90b18a202fd6290f237d7b100cf4 100644
--- a/apps/common/api.py
+++ b/apps/common/api.py
@@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
#
+
+import os
import json
+import jms_storage
from rest_framework.views import Response, APIView
from ldap3 import Server, Connection
@@ -10,6 +13,7 @@ from django.conf import settings
from .permissions import IsOrgAdmin
from .serializers import MailTestSerializer, LDAPTestSerializer
+from .models import Setting
class MailTestingAPI(APIView):
@@ -85,6 +89,78 @@ class LDAPTestingAPI(APIView):
return Response({"error": str(serializer.errors)}, status=401)
+class ReplayStorageCreateAPI(APIView):
+ permission_classes = (IsOrgAdmin,)
+
+ def post(self, request):
+ storage_data = request.data
+
+ if storage_data.get('TYPE') == 'ceph':
+ port = storage_data.get('PORT')
+ if port.isdigit():
+ storage_data['PORT'] = int(storage_data.get('PORT'))
+
+ storage_name = storage_data.pop('NAME')
+ data = {storage_name: storage_data}
+
+ if not self.is_valid(storage_data):
+ return Response({"error": _("Error: Account invalid")}, status=401)
+
+ Setting.save_storage('TERMINAL_REPLAY_STORAGE', data)
+ return Response({"msg": _('Create succeed')}, status=200)
+
+ @staticmethod
+ def is_valid(storage_data):
+ if storage_data.get('TYPE') == 'server':
+ return True
+ storage = jms_storage.get_object_storage(storage_data)
+ target = 'tests.py'
+ src = os.path.join(settings.BASE_DIR, 'common', target)
+ ok, msg = storage.upload(src=src, target=target)
+ if not ok:
+ return False
+ storage.delete(path=target)
+ return True
+
+
+class ReplayStorageDeleteAPI(APIView):
+
+ def post(self, request):
+ storage_name = str(request.data.get('name'))
+ Setting.delete_storage('TERMINAL_REPLAY_STORAGE', storage_name)
+ return Response({"msg": _('Delete succeed')}, status=200)
+
+
+class CommandStorageCreateAPI(APIView):
+ permission_classes = (IsOrgAdmin,)
+
+ def post(self, request):
+ storage_data = request.data
+ storage_name = storage_data.pop('NAME')
+ data = {storage_name: storage_data}
+ if not self.is_valid(storage_data):
+ return Response({"error": _("Error: Account invalid")}, status=401)
+
+ Setting.save_storage('TERMINAL_COMMAND_STORAGE', data)
+ return Response({"msg": _('Create succeed')}, status=200)
+
+ @staticmethod
+ def is_valid(storage_data):
+ if storage_data.get('TYPE') == 'server':
+ return True
+ storage = jms_storage.get_log_storage(storage_data)
+ return storage.ping()
+
+
+class CommandStorageDeleteAPI(APIView):
+ permission_classes = (IsOrgAdmin,)
+
+ def post(self, request):
+ storage_name = str(request.data.get('name'))
+ Setting.delete_storage('TERMINAL_COMMAND_STORAGE', storage_name)
+ return Response({"msg": _('Delete succeed')}, status=200)
+
+
class DjangoSettingsAPI(APIView):
def get(self, request):
if not settings.DEBUG:
diff --git a/apps/common/forms.py b/apps/common/forms.py
index 610e1a83e856c7a925a7fb11f8792dda35da1993..491ae779a2e47c92119ddbc31d7ff1b313da1cff 100644
--- a/apps/common/forms.py
+++ b/apps/common/forms.py
@@ -135,30 +135,34 @@ class TerminalSettingForm(BaseForm):
('hostname', _('Hostname')),
('ip', _('IP')),
)
- TERMINAL_ASSET_LIST_SORT_BY = forms.ChoiceField(
- choices=SORT_BY_CHOICES, initial='hostname', label=_("List sort by")
- )
- TERMINAL_HEARTBEAT_INTERVAL = forms.IntegerField(
- initial=5, label=_("Heartbeat interval"), help_text=_("Units: seconds")
- )
TERMINAL_PASSWORD_AUTH = forms.BooleanField(
initial=True, required=False, label=_("Password auth")
)
TERMINAL_PUBLIC_KEY_AUTH = forms.BooleanField(
initial=True, required=False, label=_("Public key auth")
)
- TERMINAL_COMMAND_STORAGE = FormEncryptDictField(
- label=_("Command storage"), help_text=_(
- "Set terminal storage setting, `default` is the using as default,"
- "You can set other storage and some terminal using"
- )
+ TERMINAL_HEARTBEAT_INTERVAL = forms.IntegerField(
+ initial=5, label=_("Heartbeat interval"), help_text=_("Units: seconds")
)
- TERMINAL_REPLAY_STORAGE = FormEncryptDictField(
- label=_("Replay storage"), help_text=_(
- "Set replay storage setting, `default` is the using as default,"
- "You can set other storage and some terminal using"
- )
+ TERMINAL_ASSET_LIST_SORT_BY = forms.ChoiceField(
+ choices=SORT_BY_CHOICES, initial='hostname', label=_("List sort by")
)
+ # TERMINAL_COMMAND_STORAGE = FormEncryptDictField(
+ # label=_("Command storage"), help_text=_(
+ # "Set terminal storage setting, `default` is the using as default,"
+ # "You can set other storage and some terminal using"
+ # )
+ # )
+ # TERMINAL_REPLAY_STORAGE = FormEncryptDictField(
+ # label=_("Replay storage"), help_text=_(
+ # "Set replay storage setting, `default` is the using as default,"
+ # "You can set other storage and some terminal using"
+ # )
+ # )
+
+
+class TerminalCommandStorage(BaseForm):
+ pass
class SecuritySettingForm(BaseForm):
diff --git a/apps/common/models.py b/apps/common/models.py
index 61f5512c952f57fc8bbc4b14413453b6cd298a61..812d491a9a81ce871acaa5791a60b6d10ccb2745 100644
--- a/apps/common/models.py
+++ b/apps/common/models.py
@@ -67,6 +67,30 @@ class Setting(models.Model):
except json.JSONDecodeError as e:
raise ValueError("Json dump error: {}".format(str(e)))
+ @classmethod
+ def save_storage(cls, name, data):
+ obj = cls.objects.filter(name=name).first()
+ if not obj:
+ obj = cls()
+ obj.name = name
+ obj.encrypted = True
+ obj.cleaned_value = data
+ else:
+ value = obj.cleaned_value
+ value.update(data)
+ obj.cleaned_value = value
+ obj.save()
+ return obj
+
+ @classmethod
+ def delete_storage(cls, name, storage_name):
+ obj = cls.objects.get(name=name)
+ value = obj.cleaned_value
+ value.pop(storage_name, '')
+ obj.cleaned_value = value
+ obj.save()
+ return True
+
@classmethod
def refresh_all_settings(cls):
try:
diff --git a/apps/common/templates/common/command_storage_create.html b/apps/common/templates/common/command_storage_create.html
new file mode 100644
index 0000000000000000000000000000000000000000..0f631161faee41aeb40e399313712a4da738aca9
--- /dev/null
+++ b/apps/common/templates/common/command_storage_create.html
@@ -0,0 +1,177 @@
+{#{% extends 'base.html' %}#}
+{% extends '_base_create_update.html' %}
+{% load static %}
+{% load bootstrap3 %}
+{% load i18n %}
+{% load common_tags %}
+
+{% block content %}
+
+{% endblock %}
+
+{% block custom_foot_js %}
+
+{% endblock %}
diff --git a/apps/common/templates/common/replay_storage_create.html b/apps/common/templates/common/replay_storage_create.html
new file mode 100644
index 0000000000000000000000000000000000000000..d717a508db9d97ecc56ed940932b1a375d6ff69e
--- /dev/null
+++ b/apps/common/templates/common/replay_storage_create.html
@@ -0,0 +1,242 @@
+{#{% extends 'base.html' %}#}
+{% extends '_base_create_update.html' %}
+{% load static %}
+{% load bootstrap3 %}
+{% load i18n %}
+{% load common_tags %}
+
+{% block content %}
+
+{% endblock %}
+
+{% block custom_foot_js %}
+
+{% endblock %}
diff --git a/apps/common/templates/common/terminal_setting.html b/apps/common/templates/common/terminal_setting.html
index 320f628b01d58b843858d23f85d9e59b3587928e..f75dea79c84da2de71b76937b4faa789ac004aeb 100644
--- a/apps/common/templates/common/terminal_setting.html
+++ b/apps/common/templates/common/terminal_setting.html
@@ -63,6 +63,14 @@
{% endif %}
{% endfor %}
+
+
{% trans "Command storage" %}
@@ -71,6 +79,7 @@
{% trans 'Name' %} |
{% trans 'Type' %} |
+ {% trans 'Action' %} |
@@ -78,10 +87,13 @@
{{ name }} |
{{ setting.TYPE }} |
+ {% trans 'Delete' %} |
{% endfor %}
+ {% trans 'Add' %}
+
{% trans "Replay storage" %}
@@ -89,6 +101,7 @@
{% trans 'Name' %} |
{% trans 'Type' %} |
+ {% trans 'Action' %} |
@@ -96,18 +109,14 @@
{{ name }} |
{{ setting.TYPE }} |
+ {% trans 'Delete' %} |
{% endfor %}
+ {% trans 'Add' %}
+
-
@@ -116,40 +125,63 @@
-
{% endblock %}
{% block custom_foot_js %}
-
+
{% endblock %}
diff --git a/apps/common/urls/api_urls.py b/apps/common/urls/api_urls.py
index 5b44684ec4cb7b61bef6318ad523386c396e5181..3c86a3a2a8366f08381bddbd88278bc974a9a4c1 100644
--- a/apps/common/urls/api_urls.py
+++ b/apps/common/urls/api_urls.py
@@ -9,5 +9,9 @@ app_name = 'common'
urlpatterns = [
path('mail/testing/', api.MailTestingAPI.as_view(), name='mail-testing'),
path('ldap/testing/', api.LDAPTestingAPI.as_view(), name='ldap-testing'),
+ path('terminal/replay-storage/create/', api.ReplayStorageCreateAPI.as_view(), name='replay-storage-create'),
+ path('terminal/replay-storage/delete/', api.ReplayStorageDeleteAPI.as_view(), name='replay-storage-delete'),
+ path('terminal/command-storage/create/', api.CommandStorageCreateAPI.as_view(), name='command-storage-create'),
+ path('terminal/command-storage/delete/', api.CommandStorageDeleteAPI.as_view(), name='command-storage-delete'),
# path('django-settings/', api.DjangoSettingsAPI.as_view(), name='django-settings'),
]
diff --git a/apps/common/urls/view_urls.py b/apps/common/urls/view_urls.py
index e7ccddd064216dd22f0f64502823d49e33986870..8c2b91297a98a25a5ed6039d65d2f16994a9d046 100644
--- a/apps/common/urls/view_urls.py
+++ b/apps/common/urls/view_urls.py
@@ -11,5 +11,7 @@ urlpatterns = [
url(r'^email/$', views.EmailSettingView.as_view(), name='email-setting'),
url(r'^ldap/$', views.LDAPSettingView.as_view(), name='ldap-setting'),
url(r'^terminal/$', views.TerminalSettingView.as_view(), name='terminal-setting'),
+ url(r'^terminal/replay-storage/create$', views.ReplayStorageCreateView.as_view(), name='replay-storage-create'),
+ url(r'^terminal/command-storage/create$', views.CommandStorageCreateView.as_view(), name='command-storage-create'),
url(r'^security/$', views.SecuritySettingView.as_view(), name='security-setting'),
]
diff --git a/apps/common/utils.py b/apps/common/utils.py
index ec55f43a168009e007d400d08b1125e1c1d7e6bb..e8476194f67f413296d0ed931bc0ce1121510736 100644
--- a/apps/common/utils.py
+++ b/apps/common/utils.py
@@ -387,6 +387,49 @@ def get_request_ip(request):
return login_ip
+def get_command_storage_or_create_default_storage():
+ from common.models import common_settings, Setting
+ name = 'TERMINAL_COMMAND_STORAGE'
+ default = {'default': {'TYPE': 'server'}}
+ command_storage = common_settings.TERMINAL_COMMAND_STORAGE
+ if command_storage is None:
+ obj = Setting()
+ obj.name = name
+ obj.encrypted = True
+ obj.cleaned_value = default
+ obj.save()
+ if isinstance(command_storage, dict) and not command_storage:
+ obj = Setting.objects.get(name=name)
+ value = obj.cleaned_value
+ value.update(default)
+ obj.cleaned_value = value
+ obj.save()
+ command_storage = common_settings.TERMINAL_COMMAND_STORAGE
+ return command_storage
+
+
+def get_replay_storage_or_create_default_storage():
+ from common.models import common_settings, Setting
+ name = 'TERMINAL_REPLAY_STORAGE'
+ default = {'default': {'TYPE': 'server'}}
+ replay_storage = common_settings.TERMINAL_REPLAY_STORAGE
+ if replay_storage is None:
+ obj = Setting()
+ obj.name = name
+ obj.encrypted = True
+ obj.cleaned_value = default
+ obj.save()
+ replay_storage = common_settings.TERMINAL_REPLAY_STORAGE
+ if isinstance(replay_storage, dict) and not replay_storage:
+ obj = Setting.objects.get(name=name)
+ value = obj.cleaned_value
+ value.update(default)
+ obj.cleaned_value = value
+ obj.save()
+ replay_storage = common_settings.TERMINAL_REPLAY_STORAGE
+ return replay_storage
+
+
class TeeObj:
origin_stdout = sys.stdout
diff --git a/apps/common/views.py b/apps/common/views.py
index 08c4828f912d936b2c0c9aa4900373d1da003cb3..04d844c04051f65fe690449515e2f8649468dbd5 100644
--- a/apps/common/views.py
+++ b/apps/common/views.py
@@ -4,10 +4,12 @@ from django.contrib import messages
from django.utils.translation import ugettext as _
from django.conf import settings
+from common.models import common_settings
from .forms import EmailSettingForm, LDAPSettingForm, BasicSettingForm, \
TerminalSettingForm, SecuritySettingForm
from common.permissions import SuperUserRequiredMixin
from .signals import ldap_auth_enable
+from . import utils
class BasicSettingView(SuperUserRequiredMixin, TemplateView):
@@ -95,14 +97,15 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView):
template_name = "common/terminal_setting.html"
def get_context_data(self, **kwargs):
- command_storage = settings.TERMINAL_COMMAND_STORAGE
- replay_storage = settings.TERMINAL_REPLAY_STORAGE
+ command_storage = utils.get_command_storage_or_create_default_storage()
+ replay_storage = utils.get_replay_storage_or_create_default_storage()
+
context = {
'app': _('Settings'),
'action': _('Terminal setting'),
'form': self.form_class(),
'replay_storage': replay_storage,
- 'command_storage': command_storage,
+ 'command_storage': command_storage
}
kwargs.update(context)
return super().get_context_data(**kwargs)
@@ -120,6 +123,30 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView):
return render(request, self.template_name, context)
+class ReplayStorageCreateView(SuperUserRequiredMixin, TemplateView):
+ template_name = 'common/replay_storage_create.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Settings'),
+ 'action': _('Create replay storage')
+ }
+ kwargs.update(context)
+ return super().get_context_data(**kwargs)
+
+
+class CommandStorageCreateView(SuperUserRequiredMixin, TemplateView):
+ template_name = 'common/command_storage_create.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Settings'),
+ 'action': _('Create command storage')
+ }
+ kwargs.update(context)
+ return super().get_context_data(**kwargs)
+
+
class SecuritySettingView(SuperUserRequiredMixin, TemplateView):
form_class = SecuritySettingForm
template_name = "common/security_setting.html"
diff --git a/apps/templates/_base_create_update.html b/apps/templates/_base_create_update.html
index ec14da79b0efccc4e5c991808992c8f799b04d43..be3813804a7278c1baa5991f6ee6c707cacc8023 100644
--- a/apps/templates/_base_create_update.html
+++ b/apps/templates/_base_create_update.html
@@ -31,8 +31,8 @@
{% if form.errors.all %}
- {{ form.errors.all }}
-
+ {{ form.errors.all }}
+
{% endif %}
{% block form %}
{% endblock %}
diff --git a/apps/terminal/backends/__init__.py b/apps/terminal/backends/__init__.py
index 9a1c338f51c0bca39c1e21ec40ff53958be23500..1c454a32d7e22b0b75ab9755d8ae9ad1df9074c7 100644
--- a/apps/terminal/backends/__init__.py
+++ b/apps/terminal/backends/__init__.py
@@ -2,6 +2,9 @@ from importlib import import_module
from django.conf import settings
from .command.serializers import SessionCommandSerializer
+from common import utils
+from common.models import common_settings, Setting
+
TYPE_ENGINE_MAPPING = {
'elasticsearch': 'terminal.backends.command.es',
}
@@ -16,7 +19,9 @@ def get_command_storage():
def get_terminal_command_storages():
storage_list = {}
- for name, params in settings.TERMINAL_COMMAND_STORAGE.items():
+ command_storage = utils.get_command_storage_or_create_default_storage()
+
+ for name, params in command_storage.items():
tp = params['TYPE']
if tp == 'server':
storage = get_command_storage()
diff --git a/apps/terminal/forms.py b/apps/terminal/forms.py
index dbba3cb01c5e29c30a628bd92a15ad1ab0269947..55997a31b00f53bf91f886368ce0a18646505cfa 100644
--- a/apps/terminal/forms.py
+++ b/apps/terminal/forms.py
@@ -2,36 +2,39 @@
#
from django import forms
-from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from .models import Terminal
def get_all_command_storage():
- # storage_choices = []
- from common.models import Setting
- Setting.refresh_all_settings()
- for k, v in settings.TERMINAL_COMMAND_STORAGE.items():
- yield (k, k)
+ from common import utils
+ command_storage = utils.get_command_storage_or_create_default_storage()
+ command_storage_choice = []
+ for k, v in command_storage.items():
+ command_storage_choice.append((k, k))
+
+ return command_storage_choice
def get_all_replay_storage():
- # storage_choices = []
- from common.models import Setting
- Setting.refresh_all_settings()
- for k, v in settings.TERMINAL_REPLAY_STORAGE.items():
- yield (k, k)
+ from common import utils
+ replay_storage = utils.get_replay_storage_or_create_default_storage()
+ replay_storage_choice = []
+ for k, v in replay_storage.items():
+ replay_storage_choice.append((k, k))
+
+ return replay_storage_choice
class TerminalForm(forms.ModelForm):
command_storage = forms.ChoiceField(
- choices=get_all_command_storage(),
+ choices=get_all_command_storage,
label=_("Command storage"),
help_text=_("Command can store in server db or ES, default to server, more see docs"),
)
replay_storage = forms.ChoiceField(
- choices=get_all_replay_storage(),
+ choices=get_all_replay_storage,
label=_("Replay storage"),
help_text=_("Replay file can store in server disk, AWS S3, Aliyun OSS, default to server, more see docs"),
)