[Merge] merge with vpc

pull/1147/head
ibuler 2018-03-26 09:56:25 +08:00
commit ac1e319cd9
42 changed files with 1317 additions and 411 deletions

View File

@ -3,3 +3,4 @@ from .asset import *
from .label import * from .label import *
from .system_user import * from .system_user import *
from .node import * from .node import *
from .domain import *

55
apps/assets/api/domain.py Normal file
View File

@ -0,0 +1,55 @@
# ~*~ coding: utf-8 ~*~
from rest_framework_bulk import BulkModelViewSet
from rest_framework.views import APIView, Response
from rest_framework.generics import RetrieveAPIView
from django.views.generic.detail import SingleObjectMixin
from common.utils import get_logger
from ..hands import IsSuperUser, IsSuperUserOrAppUser
from ..models import Domain, Gateway
from ..utils import test_gateway_connectability
from .. import serializers
logger = get_logger(__file__)
__all__ = ['DomainViewSet', 'GatewayViewSet', "GatewayTestConnectionApi"]
class DomainViewSet(BulkModelViewSet):
queryset = Domain.objects.all()
permission_classes = (IsSuperUser,)
serializer_class = serializers.DomainSerializer
def get_serializer_class(self):
if self.request.query_params.get('gateway'):
return serializers.DomainWithGatewaySerializer
return super().get_serializer_class()
def get_permissions(self):
if self.request.query_params.get('gateway'):
self.permission_classes = (IsSuperUserOrAppUser,)
return super().get_permissions()
class GatewayViewSet(BulkModelViewSet):
filter_fields = ("domain",)
search_fields = filter_fields
queryset = Gateway.objects.all()
permission_classes = (IsSuperUser,)
serializer_class = serializers.GatewaySerializer
class GatewayTestConnectionApi(SingleObjectMixin, APIView):
permission_classes = (IsSuperUser,)
model = Gateway
object = None
def get(self, request, *args, **kwargs):
self.object = self.get_object(Gateway.objects.all())
ok, e = test_gateway_connectability(self.object)
if ok:
return Response("ok")
else:
return Response({"failed": e}, status=404)

View File

@ -3,3 +3,4 @@
from .asset import * from .asset import *
from .label import * from .label import *
from .user import * from .user import *
from .domain import *

View File

@ -16,6 +16,7 @@ class AssetCreateForm(forms.ModelForm):
fields = [ fields = [
'hostname', 'ip', 'public_ip', 'port', 'comment', 'hostname', 'ip', 'public_ip', 'port', 'comment',
'nodes', 'is_active', 'admin_user', 'labels', 'platform', 'nodes', 'is_active', 'admin_user', 'labels', 'platform',
'domain',
] ]
widgets = { widgets = {
@ -29,6 +30,9 @@ class AssetCreateForm(forms.ModelForm):
'class': 'select2', 'data-placeholder': _('Labels') 'class': 'select2', 'data-placeholder': _('Labels')
}), }),
'port': forms.TextInput(), 'port': forms.TextInput(),
'domain': forms.Select(attrs={
'class': 'select2', 'data-placeholder': _('Domain')
}),
} }
help_texts = { help_texts = {
'hostname': '* required', 'hostname': '* required',
@ -38,7 +42,8 @@ class AssetCreateForm(forms.ModelForm):
'root or other NOPASSWD sudo privilege user existed in asset,' 'root or other NOPASSWD sudo privilege user existed in asset,'
'If asset is windows or other set any one, more see admin user left menu' 'If asset is windows or other set any one, more see admin user left menu'
), ),
'platform': _("* required Must set exact system platform, Windows, Linux ...") 'platform': _("* required Must set exact system platform, Windows, Linux ..."),
'domain': _("If your have some network not connect with each other, you can set domain")
} }
@ -48,6 +53,7 @@ class AssetUpdateForm(forms.ModelForm):
fields = [ fields = [
'hostname', 'ip', 'port', 'nodes', 'is_active', 'platform', 'hostname', 'ip', 'port', 'nodes', 'is_active', 'platform',
'public_ip', 'number', 'comment', 'admin_user', 'labels', 'public_ip', 'number', 'comment', 'admin_user', 'labels',
'domain',
] ]
widgets = { widgets = {
'nodes': forms.SelectMultiple(attrs={ 'nodes': forms.SelectMultiple(attrs={
@ -60,6 +66,9 @@ class AssetUpdateForm(forms.ModelForm):
'class': 'select2', 'data-placeholder': _('Labels') 'class': 'select2', 'data-placeholder': _('Labels')
}), }),
'port': forms.TextInput(), 'port': forms.TextInput(),
'domain': forms.Select(attrs={
'class': 'select2', 'data-placeholder': _('Domain')
}),
} }
help_texts = { help_texts = {
'hostname': '* required', 'hostname': '* required',
@ -70,7 +79,8 @@ class AssetUpdateForm(forms.ModelForm):
'root or other NOPASSWD sudo privilege user existed in asset,' 'root or other NOPASSWD sudo privilege user existed in asset,'
'If asset is windows or other set any one, more see admin user left menu' 'If asset is windows or other set any one, more see admin user left menu'
), ),
'platform': _("* required Must set exact system platform, Windows, Linux ...") 'platform': _("* required Must set exact system platform, Windows, Linux ..."),
'domain': _("If your have some network not connect with each other, you can set domain")
} }

View File

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
#
from django import forms
from django.utils.translation import gettext_lazy as _
from ..models import Domain, Asset, Gateway
from .user import PasswordAndKeyAuthForm
__all__ = ['DomainForm', 'GatewayForm']
class DomainForm(forms.ModelForm):
assets = forms.ModelMultipleChoiceField(
queryset=Asset.objects.all(), label=_('Asset'), required=False,
widget=forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Select assets')}
)
)
class Meta:
model = Domain
fields = ['name', 'comment', 'assets']
def __init__(self, *args, **kwargs):
if kwargs.get('instance', None):
initial = kwargs.get('initial', {})
initial['assets'] = kwargs['instance'].assets.all()
super().__init__(*args, **kwargs)
def save(self, commit=True):
instance = super().save(commit=commit)
assets = self.cleaned_data['assets']
instance.assets.set(assets)
return instance
class GatewayForm(PasswordAndKeyAuthForm):
def save(self, commit=True):
# Because we define custom field, so we need rewrite :method: `save`
instance = super().save()
password = self.cleaned_data.get('password')
private_key, public_key = super().gen_keys()
instance.set_auth(password=password, private_key=private_key)
return instance
class Meta:
model = Gateway
fields = [
'name', 'ip', 'port', 'username', 'protocol', 'domain', 'password',
'private_key_file', 'is_active', 'comment',
]
widgets = {
'name': forms.TextInput(attrs={'placeholder': _('Name')}),
'username': forms.TextInput(attrs={'placeholder': _('Username')}),
}
help_texts = {
'name': '* required',
'username': '* required',
}

View File

@ -8,7 +8,7 @@ from common.utils import validate_ssh_private_key, ssh_pubkey_gen, get_logger
logger = get_logger(__file__) logger = get_logger(__file__)
__all__ = [ __all__ = [
'FileForm', 'SystemUserForm', 'AdminUserForm', 'FileForm', 'SystemUserForm', 'AdminUserForm', 'PasswordAndKeyAuthForm',
] ]

View File

@ -5,6 +5,7 @@ from .user import AdminUser, SystemUser
from .label import Label from .label import Label
from .cluster import * from .cluster import *
from .group import * from .group import *
from .domain import *
from .node import * from .node import *
from .asset import * from .asset import *
from .utils import * from .utils import *

View File

@ -4,14 +4,13 @@
import uuid import uuid
import logging import logging
import random
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.core.cache import cache from django.core.cache import cache
from ..const import ASSET_ADMIN_CONN_CACHE_KEY from ..const import ASSET_ADMIN_CONN_CACHE_KEY
from .cluster import Cluster
from .group import AssetGroup
from .user import AdminUser, SystemUser from .user import AdminUser, SystemUser
__all__ = ['Asset'] __all__ = ['Asset']
@ -50,6 +49,7 @@ class Asset(models.Model):
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True) ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname')) hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname'))
port = models.IntegerField(default=22, verbose_name=_('Port')) port = models.IntegerField(default=22, verbose_name=_('Port'))
domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', verbose_name=_("Domain"))
nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes")) nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes"))
is_active = models.BooleanField(default=True, verbose_name=_('Is active')) is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
@ -122,12 +122,15 @@ class Asset(models.Model):
return False return False
def to_json(self): def to_json(self):
return { info = {
'id': self.id, 'id': self.id,
'hostname': self.hostname, 'hostname': self.hostname,
'ip': self.ip, 'ip': self.ip,
'port': self.port, 'port': self.port,
} }
if self.domain and self.domain.gateway_set.all():
info["gateways"] = [d.id for d in self.domain.gateway_set.all()]
return info
def _to_secret_json(self): def _to_secret_json(self):
""" """
@ -168,7 +171,6 @@ class Asset(models.Model):
try: try:
asset.save() asset.save()
asset.system_users = [choice(SystemUser.objects.all()) for i in range(3)] asset.system_users = [choice(SystemUser.objects.all()) for i in range(3)]
asset.groups = [choice(AssetGroup.objects.all()) for i in range(3)]
logger.debug('Generate fake asset : %s' % asset.ip) logger.debug('Generate fake asset : %s' % asset.ip)
except IntegrityError: except IntegrityError:
print('Error continue') print('Error continue')

126
apps/assets/models/base.py Normal file
View File

@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
#
import os
import uuid
from hashlib import md5
import sshpubkeys
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from common.utils import get_signer, ssh_key_string_to_obj, ssh_key_gen
from .utils import private_key_validator
signer = get_signer()
class AssetUser(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
username = models.CharField(max_length=128, verbose_name=_('Username'))
_password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password'))
_private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator, ])
_public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key'))
comment = models.TextField(blank=True, verbose_name=_('Comment'))
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by'))
@property
def password(self):
if self._password:
return signer.unsign(self._password)
else:
return None
@password.setter
def password(self, password_raw):
raise AttributeError("Using set_auth do that")
# self._password = signer.sign(password_raw)
@property
def private_key(self):
if self._private_key:
return signer.unsign(self._private_key)
@private_key.setter
def private_key(self, private_key_raw):
raise AttributeError("Using set_auth do that")
# self._private_key = signer.sign(private_key_raw)
@property
def private_key_obj(self):
if self._private_key:
key_str = signer.unsign(self._private_key)
return ssh_key_string_to_obj(key_str, password=self.password)
else:
return None
@property
def private_key_file(self):
if not self.private_key_obj:
return None
project_dir = settings.PROJECT_DIR
tmp_dir = os.path.join(project_dir, 'tmp')
key_str = signer.unsign(self._private_key)
key_name = '.' + md5(key_str.encode('utf-8')).hexdigest()
key_path = os.path.join(tmp_dir, key_name)
if not os.path.exists(key_path):
self.private_key_obj.write_private_key_file(key_path)
os.chmod(key_path, 0o400)
return key_path
@property
def public_key(self):
key = signer.unsign(self._public_key)
if key:
return key
else:
return None
@property
def public_key_obj(self):
if self.public_key:
try:
return sshpubkeys.SSHKey(self.public_key)
except TabError:
pass
return None
def set_auth(self, password=None, private_key=None, public_key=None):
update_fields = []
if password:
self._password = signer.sign(password)
update_fields.append('_password')
if private_key:
self._private_key = signer.sign(private_key)
update_fields.append('_private_key')
if public_key:
self._public_key = signer.sign(public_key)
update_fields.append('_public_key')
if update_fields:
self.save(update_fields=update_fields)
def auto_gen_auth(self):
password = str(uuid.uuid4())
private_key, public_key = ssh_key_gen(
username=self.name, password=password
)
self.set_auth(password=password,
private_key=private_key,
public_key=public_key)
def _to_secret_json(self):
"""Push system user use it"""
return {
'name': self.name,
'username': self.username,
'password': self.password,
'public_key': self.public_key,
'private_key': self.private_key_file,
}
class Meta:
abstract = True

View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
#
import uuid
import random
from django.db import models
from django.utils.translation import ugettext_lazy as _
from .base import AssetUser
__all__ = ['Domain', 'Gateway']
class Domain(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
comment = models.TextField(blank=True, verbose_name=_('Comment'))
date_created = models.DateTimeField(auto_now_add=True, null=True,
verbose_name=_('Date created'))
def __str__(self):
return self.name
def has_gateway(self):
return self.gateway_set.filter(is_active=True).exists()
@property
def gateways(self):
return self.gateway_set.filter(is_active=True)
def random_gateway(self):
return random.choice(self.gateways)
class Gateway(AssetUser):
SSH_PROTOCOL = 'ssh'
RDP_PROTOCOL = 'rdp'
PROTOCOL_CHOICES = (
(SSH_PROTOCOL, 'ssh'),
(RDP_PROTOCOL, 'rdp'),
)
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
port = models.IntegerField(default=22, verbose_name=_('Port'))
protocol = models.CharField(choices=PROTOCOL_CHOICES, max_length=16, default=SSH_PROTOCOL, verbose_name=_("Protocol"))
domain = models.ForeignKey(Domain, verbose_name=_("Domain"))
comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=_("Comment"))
is_active = models.BooleanField(default=True, verbose_name=_("Is active"))
def __str__(self):
return self.name

View File

@ -2,20 +2,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import os
import logging import logging
import uuid
from hashlib import md5
import sshpubkeys
from django.core.cache import cache from django.core.cache import cache
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from common.utils import get_signer, ssh_key_string_to_obj, ssh_key_gen from common.utils import get_signer
from .utils import private_key_validator
from ..const import SYSTEM_USER_CONN_CACHE_KEY from ..const import SYSTEM_USER_CONN_CACHE_KEY
from .base import AssetUser
__all__ = ['AdminUser', 'SystemUser',] __all__ = ['AdminUser', 'SystemUser',]
@ -23,117 +18,6 @@ logger = logging.getLogger(__name__)
signer = get_signer() signer = get_signer()
class AssetUser(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
username = models.CharField(max_length=128, verbose_name=_('Username'))
_password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password'))
_private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator, ])
_public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key'))
comment = models.TextField(blank=True, verbose_name=_('Comment'))
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by'))
@property
def password(self):
if self._password:
return signer.unsign(self._password)
else:
return None
@password.setter
def password(self, password_raw):
raise AttributeError("Using set_auth do that")
# self._password = signer.sign(password_raw)
@property
def private_key(self):
if self._private_key:
return signer.unsign(self._private_key)
@private_key.setter
def private_key(self, private_key_raw):
raise AttributeError("Using set_auth do that")
# self._private_key = signer.sign(private_key_raw)
@property
def private_key_obj(self):
if self._private_key:
key_str = signer.unsign(self._private_key)
return ssh_key_string_to_obj(key_str, password=self.password)
else:
return None
@property
def private_key_file(self):
if not self.private_key_obj:
return None
project_dir = settings.PROJECT_DIR
tmp_dir = os.path.join(project_dir, 'tmp')
key_str = signer.unsign(self._private_key)
key_name = '.' + md5(key_str.encode('utf-8')).hexdigest()
key_path = os.path.join(tmp_dir, key_name)
if not os.path.exists(key_path):
self.private_key_obj.write_private_key_file(key_path)
os.chmod(key_path, 0o400)
return key_path
@property
def public_key(self):
key = signer.unsign(self._public_key)
if key:
return key
else:
return None
@property
def public_key_obj(self):
if self.public_key:
try:
return sshpubkeys.SSHKey(self.public_key)
except TabError:
pass
return None
def set_auth(self, password=None, private_key=None, public_key=None):
update_fields = []
if password:
self._password = signer.sign(password)
update_fields.append('_password')
if private_key:
self._private_key = signer.sign(private_key)
update_fields.append('_private_key')
if public_key:
self._public_key = signer.sign(public_key)
update_fields.append('_public_key')
if update_fields:
self.save(update_fields=update_fields)
def auto_gen_auth(self):
password = str(uuid.uuid4())
private_key, public_key = ssh_key_gen(
username=self.name, password=password
)
self.set_auth(password=password,
private_key=private_key,
public_key=public_key)
def _to_secret_json(self):
"""Push system user use it"""
return {
'name': self.name,
'username': self.username,
'password': self.password,
'public_key': self.public_key,
'private_key': self.private_key_file,
}
class Meta:
abstract = True
class AdminUser(AssetUser): class AdminUser(AssetUser):
""" """
A privileged user that ansible can use it to push system user and so on A privileged user that ansible can use it to push system user and so on

View File

@ -10,15 +10,15 @@ __all__ = ['init_model', 'generate_fake']
def init_model(): def init_model():
from . import Cluster, SystemUser, AdminUser, AssetGroup, Asset from . import SystemUser, AdminUser, Asset
for cls in [Cluster, SystemUser, AdminUser, AssetGroup, Asset]: for cls in [SystemUser, AdminUser, Asset]:
if hasattr(cls, 'initial'): if hasattr(cls, 'initial'):
cls.initial() cls.initial()
def generate_fake(): def generate_fake():
from . import Cluster, SystemUser, AdminUser, AssetGroup, Asset from . import SystemUser, AdminUser, Asset
for cls in [Cluster, SystemUser, AdminUser, AssetGroup, Asset]: for cls in [SystemUser, AdminUser, Asset]:
if hasattr(cls, 'generate_fake'): if hasattr(cls, 'generate_fake'):
cls.generate_fake() cls.generate_fake()

View File

@ -6,3 +6,4 @@ from .admin_user import *
from .label import * from .label import *
from .system_user import * from .system_user import *
from .node import * from .node import *
from .domain import *

View File

@ -38,7 +38,7 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
model = Asset model = Asset
fields = ( fields = (
"id", "hostname", "ip", "port", "system_users_granted", "id", "hostname", "ip", "port", "system_users_granted",
"is_active", "system_users_join", "os", "is_active", "system_users_join", "os", 'domain',
"platform", "comment" "platform", "comment"
) )

View File

@ -1,46 +0,0 @@
# -*- coding: utf-8 -*-
#
from rest_framework import serializers
from common.mixins import BulkSerializerMixin
from ..models import Asset, Cluster
class ClusterUpdateAssetsSerializer(serializers.ModelSerializer):
"""
集群更新资产数据结构
"""
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
class Meta:
model = Cluster
fields = ['id', 'assets']
class ClusterSerializer(BulkSerializerMixin, serializers.ModelSerializer):
"""
cluster
"""
assets_amount = serializers.SerializerMethodField()
admin_user_name = serializers.SerializerMethodField()
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
system_users = serializers.SerializerMethodField()
class Meta:
model = Cluster
fields = '__all__'
@staticmethod
def get_assets_amount(obj):
return obj.assets.count()
@staticmethod
def get_admin_user_name(obj):
try:
return obj.admin_user.name
except AttributeError:
return ''
@staticmethod
def get_system_users(obj):
return ', '.join(obj.name for obj in obj.systemuser_set.all())

View File

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
#
from rest_framework import serializers
from ..models import Domain, Gateway
class DomainSerializer(serializers.ModelSerializer):
asset_count = serializers.SerializerMethodField()
gateway_count = serializers.SerializerMethodField()
class Meta:
model = Domain
fields = '__all__'
@staticmethod
def get_asset_count(obj):
return obj.assets.count()
@staticmethod
def get_gateway_count(obj):
return obj.gateway_set.all().count()
class GatewaySerializer(serializers.ModelSerializer):
class Meta:
model = Gateway
fields = [
'id', 'name', 'ip', 'port', 'protocol', 'username',
'domain', 'is_active', 'date_created', 'date_updated',
'created_by', 'comment',
]
class GatewayWithAuthSerializer(GatewaySerializer):
def get_field_names(self, declared_fields, info):
fields = super().get_field_names(declared_fields, info)
fields.extend(
['password', 'private_key']
)
return fields
class DomainWithGatewaySerializer(serializers.ModelSerializer):
gateways = GatewayWithAuthSerializer(many=True, read_only=True)
class Meta:
model = Domain
fields = '__all__'

View File

@ -3,6 +3,7 @@ import json
import re import re
import os import os
import paramiko
from celery import shared_task from celery import shared_task
from django.core.cache import cache from django.core.cache import cache
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -12,7 +13,7 @@ from common.utils import get_object_or_none, capacity_convert, \
from common.celery import register_as_period_task, after_app_shutdown_clean, \ from common.celery import register_as_period_task, after_app_shutdown_clean, \
after_app_ready_start, app as celery_app after_app_ready_start, app as celery_app
from .models import SystemUser, AdminUser, Asset, Cluster from .models import SystemUser, AdminUser, Asset
from . import const from . import const
@ -438,3 +439,7 @@ def push_node_system_users_to_asset(node, assets):
# def push_system_user_period(): # def push_system_user_period():
# for system_user in SystemUser.objects.all(): # for system_user in SystemUser.objects.all():
# push_system_user_related_nodes(system_user) # push_system_user_related_nodes(system_user)

View File

@ -19,6 +19,7 @@
{% bootstrap_field form.port layout="horizontal" %} {% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %} {% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %} {% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans 'Auth' %}</h3> <h3>{% trans 'Auth' %}</h3>

View File

@ -24,6 +24,7 @@
{% bootstrap_field form.port layout="horizontal" %} {% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %} {% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %} {% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans 'Auth' %}</h3> <h3>{% trans 'Auth' %}</h3>

View File

@ -0,0 +1,31 @@
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap3 %}
{% load i18n %}
{% block form %}
<form id="groupForm" method="post" class="form-horizontal">
{% csrf_token %}
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.assets layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-default" type="reset"> {% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
{% endblock %}
{% block custom_foot_js %}
<script type="text/javascript">
$(document).ready(function () {
$('.select2').select2({
closeOnSelect: false
});
});
</script>
{% endblock %}

View File

@ -0,0 +1,132 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link href='{% static "css/plugins/select2/select2.min.css" %}' rel="stylesheet">
<script src='{% static "js/plugins/select2/select2.full.min.js" %}'></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active">
<a href="{% url 'assets:domain-detail' pk=object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li>
<a href="{% url 'assets:domain-gateway-list' pk=object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Gateway' %} </a>
</li>
<li class="pull-right">
<a class="btn btn-outline btn-default" href="{% url 'assets:domain-update' pk=object.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
</li>
<li class="pull-right">
<a class="btn btn-outline btn-danger btn-del">
<i class="fa fa-trash-o"></i>{% trans 'Delete' %}
</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-9" style="padding-left: 0;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label"><b>{{ object.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td>{% trans 'Name' %}:</td>
<td><b>{{ object.name }}</b></td>
</tr>
<tr>
<td>{% trans 'Asset' %}:</td>
<td><b>{{ object.assets.count }}</b></td>
</tr>
<tr>
<td>{% trans 'Gateway' %}:</td>
<td><b>{{ object.gateway_set.count }}</b></td>
</tr>
<tr>
<td>{% trans 'Date created' %}:</td>
<td><b>{{ object.date_created }}</b></td>
</tr>
<tr>
<td>{% trans 'Created by' %}:</td>
<td><b>{{ object.created_by }}</b></td>
</tr>
<tr>
<td>{% trans 'Comment' %}:</td>
<td><b>{{ object.comment }}</b></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<script>
function initTable() {
var options = {
ele: $('#domain_list_table'),
columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) {
var detail_btn = '<a href="{% url "assets:domain-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}},
{targets: 5, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "assets:domain-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
$(td).html(update_btn + del_btn)
}}
],
ajax_url: '{% url "api-assets:domain-list" %}',
columns: [
{data: "id"}, {data: "name" }, {data: "asset_count" },
{data: "gateway_count" }, {data: "comment" }, {data: "id"}
],
op_html: $('#actions').html()
};
jumpserver.initDataTable(options);
}
$(document).ready(function(){
initTable();
})
.on('click', '.btn-delete', function () {
var $this = $(this);
var $data_table = $('#domain_list_table').DataTable();
var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
var uid = $this.data('uid');
var the_url = '{% url "api-assets:domain-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
objectDelete($this, name, the_url);
setTimeout( function () {
$data_table.ajax.reload();
}, 3000);
});
</script>
{% endblock %}

View File

@ -0,0 +1,131 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link href='{% static "css/plugins/select2/select2.min.css" %}' rel="stylesheet">
<script src='{% static "js/plugins/select2/select2.full.min.js" %}'></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li>
<a href="{% url 'assets:domain-detail' pk=object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li class="active">
<a href="{% url 'assets:domain-detail' pk=object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Gateway' %} </a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-12" style="padding-left: 0;">
<div class="" id="content_start">
</div>
<div class="ibox float-e-margins">
<div class="ibox-title">
<span style="float: left"><b>{% trans 'Gateway list' %}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="uc pull-left m-r-5">
<a href="{% url 'assets:domain-gateway-create' pk=object.id %}" class="btn btn-sm btn-primary"> {% trans "Create gateway" %} </a>
</div>
<table class="table table-striped table-bordered table-hover " id="domain_list_table" >
<thead>
<tr>
<th class="text-center">
<input type="checkbox" id="check_all" class="ipt_check_all" >
</th>
<th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'IP' %}</th>
<th class="text-center">{% trans 'Port' %}</th>
<th class="text-center">{% trans 'Protocol' %}</th>
<th class="text-center">{% trans 'Username' %}</th>
<th class="text-center">{% trans 'Comment' %}</th>
<th class="text-center">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<script>
function initTable() {
var options = {
ele: $('#domain_list_table'),
columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) {
var detail_btn = '<a href="{% url "assets:domain-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}},
{targets: 7, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "assets:domain-gateway-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var test_btn = '<a class="btn btn-xs btn-warning m-l-xs btn-test" data-uid="{{ DEFAULT_PK }}">{% trans "Test connection" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
$(td).html(update_btn + test_btn + del_btn)
}}
],
ajax_url: '{% url "api-assets:gateway-list" %}?domain={{ object.id }}',
columns: [
{data: "id"}, {data: "name" }, {data: 'ip'}, {data: 'port'}, {data: "username" },
{data: "protocol"}, {data: "comment" }, {data: "id"}
],
op_html: $('#actions').html()
};
jumpserver.initDataTable(options);
}
$(document).ready(function(){
initTable();
})
.on('click', '.btn-delete', function () {
var $this = $(this);
var $data_table = $('#domain_list_table').DataTable();
var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
var uid = $this.data('uid');
var the_url = '{% url "api-assets:gateway-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
objectDelete($this, name, the_url);
setTimeout( function () {
$data_table.ajax.reload();
}, 3000);
}).on('click', '.btn-test', function () {
var $this = $(this);
var uid = $this.data('uid');
var the_url = '{% url "api-assets:test-gateway-connective" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
APIUpdateAttr({
url: the_url,
method: "GET",
success_message: "可连接",
fail_message: "连接失败"
})
})
</script>
{% endblock %}

View File

@ -0,0 +1,70 @@
{% extends '_base_list.html' %}
{% load i18n static %}
{% block table_search %}{% endblock %}
{% block table_container %}
<div class="uc pull-left m-r-5">
<a href="{% url 'assets:domain-create' %}" class="btn btn-sm btn-primary"> {% trans "Create domain" %} </a>
</div>
<table class="table table-striped table-bordered table-hover " id="domain_list_table" >
<thead>
<tr>
<th class="text-center">
<input type="checkbox" id="check_all" class="ipt_check_all" >
</th>
<th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'Asset' %}</th>
<th class="text-center">{% trans 'Gateway' %}</th>
<th class="text-center">{% trans 'Comment' %}</th>
<th class="text-center">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<script>
function initTable() {
var options = {
ele: $('#domain_list_table'),
columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) {
var detail_btn = '<a href="{% url "assets:domain-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}},
{targets: 5, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "assets:domain-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
$(td).html(update_btn + del_btn)
}}
],
ajax_url: '{% url "api-assets:domain-list" %}',
columns: [
{data: "id"}, {data: "name" }, {data: "asset_count" },
{data: "gateway_count" }, {data: "comment" }, {data: "id"}
],
op_html: $('#actions').html()
};
jumpserver.initDataTable(options);
}
$(document).ready(function(){
initTable();
})
.on('click', '.btn-delete', function () {
var $this = $(this);
var $data_table = $('#domain_list_table').DataTable();
var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
var uid = $this.data('uid');
var the_url = '{% url "api-assets:domain-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
objectDelete($this, name, the_url);
setTimeout( function () {
$data_table.ajax.reload();
}, 3000);
});
</script>
{% endblock %}

View File

@ -0,0 +1,68 @@
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap3 %}
{% block custom_head_css_js %}
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{{ action }}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<form enctype="multipart/form-data" method="post" class="form-horizontal" action="" >
{% csrf_token %}
{% if form.non_field_errors %}
<div class="alert alert-danger">
{{ form.non_field_errors }}
</div>
{% endif %}
<h3>{% trans 'Basic' %}</h3>
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
{% block auth %}
<h3>{% trans 'Auth' %}</h3>
<div class="auth-fields">
{% bootstrap_field form.username layout="horizontal" %}
{% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.private_key_file layout="horizontal" %}
</div>
{% endblock %}
<h3>{% trans 'Other' %}</h3>
{% bootstrap_field form.is_active layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -206,7 +206,7 @@
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
function updateSystemUserCluster(nodes) { function updateSystemUserNode(nodes) {
var the_url = "{% url 'api-assets:system-user-detail' pk=system_user.id %}"; var the_url = "{% url 'api-assets:system-user-detail' pk=system_user.id %}";
var body = { var body = {
nodes: Object.assign([], nodes) nodes: Object.assign([], nodes)
@ -267,7 +267,7 @@ $(document).ready(function () {
$.map(jumpserver.nodes_selected, function(value, index) { $.map(jumpserver.nodes_selected, function(value, index) {
nodes.push(index); nodes.push(index);
}); });
updateSystemUserCluster(nodes); updateSystemUserNode(nodes);
}) })
.on('click', '.btn-remove-from-node', function() { .on('click', '.btn-remove-from-node', function() {
var $this = $(this); var $this = $(this);
@ -282,7 +282,7 @@ $(document).ready(function () {
var nodes = $('.bdg_node').map(function () { var nodes = $('.bdg_node').map(function () {
return $(this).data('gid'); return $(this).data('gid');
}).get(); }).get();
updateSystemUserCluster(nodes); updateSystemUserNode(nodes);
}).on('click', '.btn-del', function () { }).on('click', '.btn-del', function () {
var $this = $(this); var $this = $(this);
var name = "{{ system_user.name}}"; var name = "{{ system_user.name}}";

View File

@ -25,6 +25,7 @@
</th> </th>
<th class="text-center">{% trans 'Name' %}</th> <th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'Username' %}</th> <th class="text-center">{% trans 'Username' %}</th>
<th class="text-center">{% trans 'Protocol' %}</th>
<th class="text-center">{% trans 'Asset' %}</th> <th class="text-center">{% trans 'Asset' %}</th>
<th class="text-center">{% trans 'Reachable' %}</th> <th class="text-center">{% trans 'Reachable' %}</th>
<th class="text-center">{% trans 'Unreachable' %}</th> <th class="text-center">{% trans 'Unreachable' %}</th>
@ -47,7 +48,7 @@ function initTable() {
var detail_btn = '<a href="{% url "assets:system-user-detail" pk=DEFAULT_PK %}">' + cellData + '</a>'; var detail_btn = '<a href="{% url "assets:system-user-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id)); $(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}}, }},
{targets: 4, createdCell: function (td, cellData) { {targets: 5, createdCell: function (td, cellData) {
var innerHtml = ""; var innerHtml = "";
if (cellData !== 0) { if (cellData !== 0) {
innerHtml = "<span class='text-navy'>" + cellData + "</span>"; innerHtml = "<span class='text-navy'>" + cellData + "</span>";
@ -56,7 +57,7 @@ function initTable() {
} }
$(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData +'">' + innerHtml + '</span>'); $(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData +'">' + innerHtml + '</span>');
}}, }},
{targets: 5, createdCell: function (td, cellData) { {targets: 6, createdCell: function (td, cellData) {
var innerHtml = ""; var innerHtml = "";
if (cellData !== 0) { if (cellData !== 0) {
innerHtml = "<span class='text-danger'>" + cellData + "</span>"; innerHtml = "<span class='text-danger'>" + cellData + "</span>";
@ -65,7 +66,7 @@ function initTable() {
} }
$(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</span>'); $(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</span>');
}}, }},
{targets: 6, createdCell: function (td, cellData, rowData) { {targets: 7, createdCell: function (td, cellData, rowData) {
var val = 0; var val = 0;
var innerHtml = ""; var innerHtml = "";
var total = rowData.assets_amount; var total = rowData.assets_amount;
@ -83,14 +84,14 @@ function initTable() {
$(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</span>'); $(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</span>');
}}, }},
{targets: 8, createdCell: function (td, cellData, rowData) { {targets: 9, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "assets:system-user-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData); var update_btn = '<a href="{% url "assets:system-user-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_admin_user_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData); var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_admin_user_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
$(td).html(update_btn + del_btn) $(td).html(update_btn + del_btn)
}}], }}],
ajax_url: '{% url "api-assets:system-user-list" %}', ajax_url: '{% url "api-assets:system-user-list" %}',
columns: [ columns: [
{data: "id" }, {data: "name" }, {data: "username" }, {data: "assets_amount" }, {data: "id" }, {data: "name" }, {data: "username" }, {data: "protocol"}, {data: "assets_amount" },
{data: "reachable_amount"}, {data: "unreachable_amount"}, {data: "id"}, {data: "comment" }, {data: "id" } {data: "reachable_amount"}, {data: "unreachable_amount"}, {data: "id"}, {data: "comment" }, {data: "id" }
], ],
op_html: $('#actions').html() op_html: $('#actions').html()

View File

@ -14,6 +14,8 @@ router.register(r'v1/admin-user', api.AdminUserViewSet, 'admin-user')
router.register(r'v1/system-user', api.SystemUserViewSet, 'system-user') router.register(r'v1/system-user', api.SystemUserViewSet, 'system-user')
router.register(r'v1/labels', api.LabelViewSet, 'label') router.register(r'v1/labels', api.LabelViewSet, 'label')
router.register(r'v1/nodes', api.NodeViewSet, 'node') router.register(r'v1/nodes', api.NodeViewSet, 'node')
router.register(r'v1/domain', api.DomainViewSet, 'domain')
router.register(r'v1/gateway', api.GatewayViewSet, 'gateway')
urlpatterns = [ urlpatterns = [
url(r'^v1/assets-bulk/$', api.AssetListUpdateApi.as_view(), name='asset-bulk-update'), url(r'^v1/assets-bulk/$', api.AssetListUpdateApi.as_view(), name='asset-bulk-update'),
@ -49,6 +51,8 @@ urlpatterns = [
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$', api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$', api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.TestNodeConnectiveApi.as_view(), name='node-test-connective'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.TestNodeConnectiveApi.as_view(), name='node-test-connective'),
url(r'^v1/gateway/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'),
] ]
urlpatterns += router.urls urlpatterns += router.urls

View File

@ -39,5 +39,15 @@ urlpatterns = [
url(r'^label/create/$', views.LabelCreateView.as_view(), name='label-create'), url(r'^label/create/$', views.LabelCreateView.as_view(), name='label-create'),
url(r'^label/(?P<pk>[0-9a-zA-Z\-]{36})/update/$', views.LabelUpdateView.as_view(), name='label-update'), url(r'^label/(?P<pk>[0-9a-zA-Z\-]{36})/update/$', views.LabelUpdateView.as_view(), name='label-update'),
url(r'^label/(?P<pk>[0-9a-zA-Z\-]{36})/delete/$', views.LabelDeleteView.as_view(), name='label-delete'), url(r'^label/(?P<pk>[0-9a-zA-Z\-]{36})/delete/$', views.LabelDeleteView.as_view(), name='label-delete'),
url(r'^domain/$', views.DomainListView.as_view(), name='domain-list'),
url(r'^domain/create/$', views.DomainCreateView.as_view(), name='domain-create'),
url(r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/$', views.DomainDetailView.as_view(), name='domain-detail'),
url(r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/update/$', views.DomainUpdateView.as_view(), name='domain-update'),
url(r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/delete/$', views.DomainDeleteView.as_view(), name='domain-delete'),
url(r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/gateway/$', views.DomainGatewayListView.as_view(), name='domain-gateway-list'),
url(r'^domain/(?P<pk>[0-9a-zA-Z\-]{36})/gateway/create/$', views.DomainGatewayCreateView.as_view(), name='domain-gateway-create'),
url(r'^domain/gateway/(?P<pk>[0-9a-zA-Z\-]{36})/update/$', views.DomainGatewayUpdateView.as_view(), name='domain-gateway-update'),
] ]

View File

@ -1,10 +1,7 @@
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
# #
from collections import defaultdict
from functools import reduce
import operator
from django.db.models import Q import paramiko
from common.utils import get_object_or_none from common.utils import get_object_or_none
from .models import Asset, SystemUser, Label from .models import Asset, SystemUser, Label
@ -44,5 +41,41 @@ class LabelFilter:
return queryset return queryset
def test_gateway_connectability(gateway):
"""
Test system cant connect his assets or not.
:param gateway:
:return:
"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
proxy_command = [
"ssh", "{}@{}".format(gateway.username, gateway.ip),
"-p", str(gateway.port), "-W", "127.0.0.1:{}".format(gateway.port),
]
if gateway.password:
proxy_command.insert(0, "sshpass -p '{}'".format(gateway.password))
if gateway.private_key:
proxy_command.append("-i {}".format(gateway.private_key_file))
try:
sock = paramiko.ProxyCommand(" ".join(proxy_command))
except paramiko.ProxyCommandFailure as e:
return False, str(e)
try:
client.connect("127.0.0.1", port=gateway.port,
username=gateway.username,
password=gateway.password,
key_filename=gateway.private_key_file,
sock=sock,
timeout=5
)
except (paramiko.SSHException, paramiko.ssh_exception.SSHException,
paramiko.AuthenticationException, TimeoutError) as e:
return False, str(e)
finally:
client.close()
return True, None

View File

@ -3,3 +3,4 @@ from .asset import *
from .system_user import * from .system_user import *
from .admin_user import * from .admin_user import *
from .label import * from .label import *
from .domain import *

View File

@ -27,7 +27,7 @@ from common.mixins import JSONResponseMixin
from common.utils import get_object_or_none, get_logger, is_uuid from common.utils import get_object_or_none, get_logger, is_uuid
from common.const import create_success_msg, update_success_msg from common.const import create_success_msg, update_success_msg
from .. import forms from .. import forms
from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser, Label, Node from ..models import Asset, AdminUser, SystemUser, Label, Node
from ..hands import AdminUserRequiredMixin from ..hands import AdminUserRequiredMixin

154
apps/assets/views/domain.py Normal file
View File

@ -0,0 +1,154 @@
# -*- coding: utf-8 -*-
#
from django.views.generic import TemplateView, CreateView, \
UpdateView, DeleteView, DetailView
from django.views.generic.detail import SingleObjectMixin
from django.utils.translation import ugettext_lazy as _
from django.urls import reverse_lazy, reverse
from common.mixins import AdminUserRequiredMixin
from common.const import create_success_msg, update_success_msg
from common.utils import get_object_or_none
from ..models import Domain, Gateway
from ..forms import DomainForm, GatewayForm
__all__ = (
"DomainListView", "DomainCreateView", "DomainUpdateView",
"DomainDetailView", "DomainDeleteView", "DomainGatewayListView",
"DomainGatewayCreateView", 'DomainGatewayUpdateView',
)
class DomainListView(AdminUserRequiredMixin, TemplateView):
template_name = 'assets/domain_list.html'
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Domain list'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class DomainCreateView(AdminUserRequiredMixin, CreateView):
model = Domain
template_name = 'assets/domain_create_update.html'
form_class = DomainForm
success_url = reverse_lazy('assets:domain-list')
success_message = create_success_msg
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Create domain'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class DomainUpdateView(AdminUserRequiredMixin, UpdateView):
model = Domain
template_name = 'assets/domain_create_update.html'
form_class = DomainForm
success_url = reverse_lazy('assets:domain-list')
success_message = update_success_msg
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Update domain'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class DomainDetailView(AdminUserRequiredMixin, DetailView):
model = Domain
template_name = 'assets/domain_detail.html'
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Domain detail'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class DomainDeleteView(AdminUserRequiredMixin, DeleteView):
model = Domain
template_name = 'delete_confirm.html'
success_url = reverse_lazy('assets:domain-list')
class DomainGatewayListView(AdminUserRequiredMixin, SingleObjectMixin, TemplateView):
template_name = 'assets/domain_gateway_list.html'
model = Domain
object = None
def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=self.model.objects.all())
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Domain gateway list'),
'object': self.get_object()
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class DomainGatewayCreateView(AdminUserRequiredMixin, CreateView):
model = Gateway
template_name = 'assets/gateway_create_update.html'
form_class = GatewayForm
success_message = create_success_msg
def get_success_url(self):
domain = self.object.domain
return reverse('assets:domain-gateway-list', kwargs={"pk": domain.id})
def get_form(self, form_class=None):
form = super().get_form(form_class=form_class)
domain_id = self.kwargs.get("pk")
domain = get_object_or_none(Domain, id=domain_id)
if domain:
form['domain'].initial = domain
return form
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Create gateway'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class DomainGatewayUpdateView(AdminUserRequiredMixin, UpdateView):
model = Gateway
template_name = 'assets/gateway_create_update.html'
form_class = GatewayForm
success_message = update_success_msg
def get_success_url(self):
domain = self.object.domain
return reverse('assets:domain-gateway-list', kwargs={"pk": domain.id})
def form_valid(self, form):
response = super().form_valid(form)
print(form.cleaned_data)
return response
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Update gateway'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)

View File

@ -359,3 +359,4 @@ def is_uuid(s):
def get_signer(): def get_signer():
signer = Signer(settings.SECRET_KEY) signer = Signer(settings.SECRET_KEY)
return signer return signer

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n" "Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-21 15:15+0800\n" "POT-Creation-Date: 2018-03-23 19:50+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n" "Language-Team: Jumpserver team<ibuler@qq.com>\n"
@ -29,28 +29,33 @@ msgstr ""
msgid "测试节点下资产是否可连接: {}" msgid "测试节点下资产是否可连接: {}"
msgstr "" msgstr ""
#: assets/forms/asset.py:23 assets/forms/asset.py:54 assets/models/asset.py:53 #: assets/forms/asset.py:24 assets/forms/asset.py:60 assets/models/asset.py:53
#: assets/models/user.py:218 assets/templates/assets/asset_detail.html:183 #: assets/models/user.py:102 assets/templates/assets/asset_detail.html:183
#: assets/templates/assets/asset_detail.html:191 #: assets/templates/assets/asset_detail.html:191
#: assets/templates/assets/system_user_detail.html:166 #: assets/templates/assets/system_user_detail.html:166
msgid "Nodes" msgid "Nodes"
msgstr "节点管理" msgstr "节点管理"
#: assets/forms/asset.py:26 assets/forms/asset.py:57 assets/forms/asset.py:93 #: assets/forms/asset.py:27 assets/forms/asset.py:63 assets/forms/asset.py:103
#: assets/forms/asset.py:97 assets/models/asset.py:57 #: assets/forms/asset.py:107 assets/models/asset.py:57
#: assets/models/cluster.py:19 assets/models/user.py:187 #: assets/models/cluster.py:19 assets/models/user.py:71
#: assets/templates/assets/asset_detail.html:73 templates/_nav.html:24 #: assets/templates/assets/asset_detail.html:73 templates/_nav.html:25
msgid "Admin user" msgid "Admin user"
msgstr "管理用户" msgstr "管理用户"
#: assets/forms/asset.py:29 assets/forms/asset.py:60 assets/models/asset.py:81 #: assets/forms/asset.py:30 assets/forms/asset.py:66 assets/models/asset.py:81
#: assets/templates/assets/asset_create.html:32 #: assets/templates/assets/asset_create.html:33
#: assets/templates/assets/asset_detail.html:220 #: assets/templates/assets/asset_detail.html:220
#: assets/templates/assets/asset_update.html:37 templates/_nav.html:26 #: assets/templates/assets/asset_update.html:38 templates/_nav.html:27
msgid "Labels" msgid "Labels"
msgstr "标签管理" msgstr "标签管理"
#: assets/forms/asset.py:38 assets/forms/asset.py:70 #: assets/forms/asset.py:34 assets/forms/asset.py:70 assets/models/asset.py:52
#: assets/models/domain.py:34
msgid "Domain"
msgstr "网域"
#: assets/forms/asset.py:42 assets/forms/asset.py:79
msgid "" msgid ""
"root or other NOPASSWD sudo privilege user existed in asset,If asset is " "root or other NOPASSWD sudo privilege user existed in asset,If asset is "
"windows or other set any one, more see admin user left menu" "windows or other set any one, more see admin user left menu"
@ -58,35 +63,44 @@ msgstr ""
"root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一" "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
"个, 更多信息查看左侧 `管理用户` 菜单" "个, 更多信息查看左侧 `管理用户` 菜单"
#: assets/forms/asset.py:41 assets/forms/asset.py:73 #: assets/forms/asset.py:45 assets/forms/asset.py:82
msgid "* required Must set exact system platform, Windows, Linux ..." msgid "* required Must set exact system platform, Windows, Linux ..."
msgstr "* required 必须准确设置操作系统平台如Windows, Linux ..." msgstr "* required 必须准确设置操作系统平台如Windows, Linux ..."
#: assets/forms/asset.py:80 assets/forms/asset.py:84 assets/forms/label.py:15 #: assets/forms/asset.py:46 assets/forms/asset.py:83
msgid ""
"If your have some network not connect with each other, you can set domain"
msgstr ""
#: assets/forms/asset.py:90 assets/forms/asset.py:94 assets/forms/domain.py:16
#: assets/forms/label.py:15
#: perms/templates/perms/asset_permission_asset.html:88 users/forms.py:270 #: perms/templates/perms/asset_permission_asset.html:88 users/forms.py:270
msgid "Select assets" msgid "Select assets"
msgstr "选择资产" msgstr "选择资产"
#: assets/forms/asset.py:89 assets/models/asset.py:52 #: assets/forms/asset.py:99 assets/models/asset.py:51
#: assets/templates/assets/admin_user_assets.html:53 #: assets/models/domain.py:32 assets/templates/assets/admin_user_assets.html:53
#: assets/templates/assets/asset_detail.html:69 #: assets/templates/assets/asset_detail.html:69
#: assets/templates/assets/domain_gateway_list.html:58
#: assets/templates/assets/system_user_asset.html:51 #: assets/templates/assets/system_user_asset.html:51
#: assets/templates/assets/user_asset_list.html:21 #: assets/templates/assets/user_asset_list.html:21
msgid "Port" msgid "Port"
msgstr "端口" msgstr "端口"
#: assets/forms/asset.py:109 assets/templates/assets/asset_create.html:36 #: assets/forms/asset.py:119 assets/templates/assets/asset_create.html:37
msgid "Select labels" msgid "Select labels"
msgstr "选择标签" msgstr "选择标签"
#: assets/forms/asset.py:112 assets/templates/assets/admin_user_detail.html:91 #: assets/forms/asset.py:122 assets/templates/assets/admin_user_detail.html:91
msgid "Select nodes" msgid "Select nodes"
msgstr "选择节点" msgstr "选择节点"
#: assets/forms/label.py:13 assets/models/asset.py:153 #: assets/forms/domain.py:14 assets/forms/label.py:13
#: assets/templates/assets/admin_user_list.html:25 #: assets/models/asset.py:156 assets/templates/assets/admin_user_list.html:25
#: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_list.html:15
#: assets/templates/assets/label_list.html:16 #: assets/templates/assets/label_list.html:16
#: assets/templates/assets/system_user_list.html:28 perms/models.py:17 #: assets/templates/assets/system_user_list.html:29 perms/models.py:17
#: terminal/backends/command/models.py:11 terminal/models.py:123 #: terminal/backends/command/models.py:11 terminal/models.py:123
#: terminal/templates/terminal/command_list.html:40 #: terminal/templates/terminal/command_list.html:40
#: terminal/templates/terminal/command_list.html:73 #: terminal/templates/terminal/command_list.html:73
@ -95,11 +109,56 @@ msgstr "选择节点"
msgid "Asset" msgid "Asset"
msgstr "资产" msgstr "资产"
#: assets/forms/domain.py:54 assets/forms/user.py:79 assets/forms/user.py:120
#: assets/models/base.py:20 assets/models/cluster.py:18
#: assets/models/domain.py:15 assets/models/group.py:20
#: assets/models/label.py:17 assets/templates/assets/admin_user_detail.html:56
#: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/domain_detail.html:56
#: assets/templates/assets/domain_gateway_list.html:56
#: assets/templates/assets/domain_list.html:14
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:26 common/models.py:26
#: common/templates/common/terminal_setting.html:67
#: common/templates/common/terminal_setting.html:85 ops/models.py:31
#: ops/templates/ops/task_detail.html:56 ops/templates/ops/task_list.html:34
#: perms/models.py:14 perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:16
#: terminal/models.py:149 terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14
#: users/models/user.py:35 users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_detail.html:63
#: users/templates/users/user_group_detail.html:55
#: users/templates/users/user_group_list.html:12
#: users/templates/users/user_list.html:23
#: users/templates/users/user_profile.html:51
#: users/templates/users/user_pubkey_update.html:53
msgid "Name"
msgstr "名称"
#: assets/forms/domain.py:55 assets/forms/user.py:80 assets/forms/user.py:121
#: assets/models/base.py:21 assets/templates/assets/admin_user_detail.html:60
#: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/domain_gateway_list.html:60
#: assets/templates/assets/system_user_detail.html:62
#: assets/templates/assets/system_user_list.html:27
#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:14
#: users/models/authentication.py:45 users/models/user.py:34
#: users/templates/users/_select_user_modal.html:14
#: users/templates/users/login.html:56
#: users/templates/users/login_log_list.html:49
#: users/templates/users/user_detail.html:67
#: users/templates/users/user_list.html:24
#: users/templates/users/user_profile.html:47
msgid "Username"
msgstr "用户名"
#: assets/forms/user.py:24 #: assets/forms/user.py:24
msgid "Password or private key passphrase" msgid "Password or private key passphrase"
msgstr "密码或密钥密码" msgstr "密码或密钥密码"
#: assets/forms/user.py:25 assets/models/user.py:30 common/forms.py:113 #: assets/forms/user.py:25 assets/models/base.py:22 common/forms.py:113
#: users/forms.py:16 users/forms.py:25 users/templates/users/login.html:59 #: users/forms.py:16 users/forms.py:25 users/templates/users/login.html:59
#: users/templates/users/reset_password.html:52 #: users/templates/users/reset_password.html:52
#: users/templates/users/user_create.html:11 #: users/templates/users/user_create.html:11
@ -121,46 +180,6 @@ msgstr "ssh密钥不合法"
msgid "Password and private key file must be input one" msgid "Password and private key file must be input one"
msgstr "密码和私钥, 必须输入一个" msgstr "密码和私钥, 必须输入一个"
#: assets/forms/user.py:79 assets/forms/user.py:120 assets/models/cluster.py:18
#: assets/models/group.py:20 assets/models/label.py:17 assets/models/user.py:28
#: assets/templates/assets/admin_user_detail.html:56
#: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:26 common/models.py:26
#: common/templates/common/terminal_setting.html:67
#: common/templates/common/terminal_setting.html:85 ops/models.py:31
#: ops/templates/ops/task_detail.html:56 ops/templates/ops/task_list.html:34
#: perms/models.py:14 perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:16
#: terminal/models.py:149 terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14
#: users/models/user.py:35 users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_detail.html:63
#: users/templates/users/user_group_detail.html:55
#: users/templates/users/user_group_list.html:12
#: users/templates/users/user_list.html:23
#: users/templates/users/user_profile.html:51
#: users/templates/users/user_pubkey_update.html:53
msgid "Name"
msgstr "名称"
#: assets/forms/user.py:80 assets/forms/user.py:121 assets/models/user.py:29
#: assets/templates/assets/admin_user_detail.html:60
#: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/system_user_detail.html:62
#: assets/templates/assets/system_user_list.html:27
#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:14
#: users/models/authentication.py:45 users/models/user.py:34
#: users/templates/users/_select_user_modal.html:14
#: users/templates/users/login.html:56
#: users/templates/users/login_log_list.html:49
#: users/templates/users/user_detail.html:67
#: users/templates/users/user_list.html:24
#: users/templates/users/user_profile.html:47
msgid "Username"
msgstr "用户名"
#: assets/forms/user.py:126 #: assets/forms/user.py:126
msgid "Auto push system user to asset" msgid "Auto push system user to asset"
msgstr "自动推送系统用户到资产" msgstr "自动推送系统用户到资产"
@ -171,10 +190,12 @@ msgid ""
"than 2 system user" "than 2 system user"
msgstr "高优先级的系统用户将会作为默认登录用户" msgstr "高优先级的系统用户将会作为默认登录用户"
#: assets/models/asset.py:50 assets/templates/assets/_asset_list_modal.html:21 #: assets/models/asset.py:49 assets/models/domain.py:31
#: assets/templates/assets/_asset_list_modal.html:21
#: assets/templates/assets/admin_user_assets.html:52 #: assets/templates/assets/admin_user_assets.html:52
#: assets/templates/assets/asset_detail.html:61 #: assets/templates/assets/asset_detail.html:61
#: assets/templates/assets/asset_list.html:87 #: assets/templates/assets/asset_list.html:87
#: assets/templates/assets/domain_gateway_list.html:57
#: assets/templates/assets/system_user_asset.html:50 #: assets/templates/assets/system_user_asset.html:50
#: assets/templates/assets/user_asset_list.html:20 common/forms.py:144 #: assets/templates/assets/user_asset_list.html:20 common/forms.py:144
#: perms/templates/perms/asset_permission_asset.html:55 #: perms/templates/perms/asset_permission_asset.html:55
@ -184,7 +205,7 @@ msgstr "高优先级的系统用户将会作为默认登录用户"
msgid "IP" msgid "IP"
msgstr "IP" msgstr "IP"
#: assets/models/asset.py:51 assets/templates/assets/_asset_list_modal.html:20 #: assets/models/asset.py:50 assets/templates/assets/_asset_list_modal.html:20
#: assets/templates/assets/admin_user_assets.html:51 #: assets/templates/assets/admin_user_assets.html:51
#: assets/templates/assets/asset_detail.html:57 #: assets/templates/assets/asset_detail.html:57
#: assets/templates/assets/asset_list.html:86 #: assets/templates/assets/asset_list.html:86
@ -196,8 +217,8 @@ msgstr "IP"
msgid "Hostname" msgid "Hostname"
msgstr "主机名" msgstr "主机名"
#: assets/models/asset.py:54 assets/models/label.py:20 #: assets/models/asset.py:54 assets/models/domain.py:36
#: assets/templates/assets/asset_detail.html:105 #: assets/models/label.py:20 assets/templates/assets/asset_detail.html:105
#: perms/templates/perms/asset_permission_list.html:70 #: perms/templates/perms/asset_permission_list.html:70
msgid "Is active" msgid "Is active"
msgstr "激活" msgstr "激活"
@ -266,10 +287,11 @@ msgstr "系统架构"
msgid "Hostname raw" msgid "Hostname raw"
msgstr "主机名原始" msgstr "主机名原始"
#: assets/models/asset.py:82 assets/models/cluster.py:28 #: assets/models/asset.py:82 assets/models/base.py:28
#: assets/models/group.py:21 assets/models/user.py:36 #: assets/models/cluster.py:28 assets/models/group.py:21
#: assets/templates/assets/admin_user_detail.html:68 #: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/asset_detail.html:117 #: assets/templates/assets/asset_detail.html:117
#: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:96 #: assets/templates/assets/system_user_detail.html:96
#: ops/templates/ops/adhoc_detail.html:86 perms/models.py:22 perms/models.py:79 #: ops/templates/ops/adhoc_detail.html:86 perms/models.py:22 perms/models.py:79
#: perms/templates/perms/asset_permission_detail.html:94 #: perms/templates/perms/asset_permission_detail.html:94
@ -278,8 +300,9 @@ msgid "Created by"
msgstr "创建者" msgstr "创建者"
#: assets/models/asset.py:83 assets/models/cluster.py:26 #: assets/models/asset.py:83 assets/models/cluster.py:26
#: assets/models/group.py:22 assets/models/label.py:23 #: assets/models/domain.py:18 assets/models/group.py:22
#: assets/templates/assets/admin_user_detail.html:64 #: assets/models/label.py:23 assets/templates/assets/admin_user_detail.html:64
#: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/system_user_detail.html:92 #: assets/templates/assets/system_user_detail.html:92
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:60 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:60
#: perms/models.py:23 perms/models.py:80 #: perms/models.py:23 perms/models.py:80
@ -289,13 +312,17 @@ msgstr "创建者"
msgid "Date created" msgid "Date created"
msgstr "创建日期" msgstr "创建日期"
#: assets/models/asset.py:84 assets/models/cluster.py:29 #: assets/models/asset.py:84 assets/models/base.py:25
#: assets/models/group.py:23 assets/models/label.py:21 assets/models/user.py:33 #: assets/models/cluster.py:29 assets/models/domain.py:16
#: assets/templates/assets/admin_user_detail.html:72 #: assets/models/domain.py:35 assets/models/group.py:23
#: assets/models/label.py:21 assets/templates/assets/admin_user_detail.html:72
#: assets/templates/assets/admin_user_list.html:29 #: assets/templates/assets/admin_user_list.html:29
#: assets/templates/assets/asset_detail.html:125 #: assets/templates/assets/asset_detail.html:125
#: assets/templates/assets/domain_detail.html:76
#: assets/templates/assets/domain_gateway_list.html:61
#: assets/templates/assets/domain_list.html:17
#: assets/templates/assets/system_user_detail.html:100 #: assets/templates/assets/system_user_detail.html:100
#: assets/templates/assets/system_user_list.html:32 common/models.py:30 #: assets/templates/assets/system_user_list.html:33 common/models.py:30
#: ops/models.py:37 perms/models.py:24 perms/models.py:81 #: ops/models.py:37 perms/models.py:24 perms/models.py:81
#: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26 #: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15 #: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15
@ -306,6 +333,14 @@ msgstr "创建日期"
msgid "Comment" msgid "Comment"
msgstr "备注" msgstr "备注"
#: assets/models/base.py:23
msgid "SSH private key"
msgstr "ssh密钥"
#: assets/models/base.py:24
msgid "SSH public key"
msgstr "ssh公钥"
#: assets/models/cluster.py:20 #: assets/models/cluster.py:20
msgid "Bandwidth" msgid "Bandwidth"
msgstr "带宽" msgstr "带宽"
@ -352,6 +387,13 @@ msgstr "默认Cluster"
msgid "Cluster" msgid "Cluster"
msgstr "集群" msgstr "集群"
#: assets/models/domain.py:33 assets/models/user.py:104
#: assets/templates/assets/domain_gateway_list.html:59
#: assets/templates/assets/system_user_detail.html:66
#: assets/templates/assets/system_user_list.html:28
msgid "Protocol"
msgstr "协议"
#: assets/models/group.py:30 perms/models.py:18 #: assets/models/group.py:30 perms/models.py:18
msgid "Asset group" msgid "Asset group"
msgstr "资产组" msgstr "资产组"
@ -385,39 +427,27 @@ msgstr "分类"
msgid "Key" msgid "Key"
msgstr "" msgstr ""
#: assets/models/user.py:31 #: assets/models/user.py:103
msgid "SSH private key"
msgstr "ssh密钥"
#: assets/models/user.py:32
msgid "SSH public key"
msgstr "ssh公钥"
#: assets/models/user.py:219
msgid "Priority" msgid "Priority"
msgstr "优先级" msgstr "优先级"
#: assets/models/user.py:220 assets/templates/assets/system_user_detail.html:66 #: assets/models/user.py:105 assets/templates/assets/_system_user.html:58
msgid "Protocol"
msgstr "协议"
#: assets/models/user.py:221 assets/templates/assets/_system_user.html:58
#: assets/templates/assets/system_user_detail.html:118 #: assets/templates/assets/system_user_detail.html:118
#: assets/templates/assets/system_user_update.html:11 #: assets/templates/assets/system_user_update.html:11
msgid "Auto push" msgid "Auto push"
msgstr "自动推送" msgstr "自动推送"
#: assets/models/user.py:222 assets/templates/assets/system_user_detail.html:70 #: assets/models/user.py:106 assets/templates/assets/system_user_detail.html:70
msgid "Sudo" msgid "Sudo"
msgstr "Sudo" msgstr "Sudo"
#: assets/models/user.py:223 assets/templates/assets/system_user_detail.html:75 #: assets/models/user.py:107 assets/templates/assets/system_user_detail.html:75
msgid "Shell" msgid "Shell"
msgstr "Shell" msgstr "Shell"
#: assets/models/user.py:266 perms/forms.py:25 perms/models.py:19 #: assets/models/user.py:150 perms/forms.py:25 perms/models.py:19
#: perms/models.py:76 perms/templates/perms/asset_permission_detail.html:136 #: perms/models.py:76 perms/templates/perms/asset_permission_detail.html:136
#: perms/templates/perms/asset_permission_list.html:69 templates/_nav.html:25 #: perms/templates/perms/asset_permission_list.html:69 templates/_nav.html:26
#: terminal/backends/command/models.py:12 terminal/models.py:124 #: terminal/backends/command/models.py:12 terminal/models.py:124
#: terminal/templates/terminal/command_list.html:48 #: terminal/templates/terminal/command_list.html:48
#: terminal/templates/terminal/command_list.html:74 #: terminal/templates/terminal/command_list.html:74
@ -431,39 +461,39 @@ msgstr "系统用户"
msgid "%(value)s is not an even number" msgid "%(value)s is not an even number"
msgstr "%(value)s is not an even number" msgstr "%(value)s is not an even number"
#: assets/tasks.py:95 assets/tasks.py:112 #: assets/tasks.py:96 assets/tasks.py:113
msgid "更新资产硬件信息" msgid "更新资产硬件信息"
msgstr "" msgstr ""
#: assets/tasks.py:131 #: assets/tasks.py:132
msgid "定期更新资产硬件信息" msgid "定期更新资产硬件信息"
msgstr "" msgstr ""
#: assets/tasks.py:209 #: assets/tasks.py:210
msgid "定期测试管理账号可连接性: {}" msgid "定期测试管理账号可连接性: {}"
msgstr "" msgstr ""
#: assets/tasks.py:216 #: assets/tasks.py:217
msgid "测试管理行号可连接性: {}" msgid "测试管理行号可连接性: {}"
msgstr "" msgstr ""
#: assets/tasks.py:226 #: assets/tasks.py:227
msgid "测试资产可连接性" msgid "测试资产可连接性"
msgstr "" msgstr ""
#: assets/tasks.py:296 #: assets/tasks.py:297
msgid "Test system user connectability: {}" msgid "Test system user connectability: {}"
msgstr "测试系统用户可连接性: {}" msgstr "测试系统用户可连接性: {}"
#: assets/tasks.py:312 #: assets/tasks.py:313
msgid "定期测试系统用户可连接性: {}" msgid "定期测试系统用户可连接性: {}"
msgstr "" msgstr ""
#: assets/tasks.py:391 #: assets/tasks.py:392
msgid "推送系统用户到节点资产: {} => {}" msgid "推送系统用户到节点资产: {} => {}"
msgstr "" msgstr ""
#: assets/tasks.py:430 #: assets/tasks.py:431
msgid "推送节点系统用户到新加入资产中: {}" msgid "推送节点系统用户到新加入资产中: {}"
msgstr "" msgstr ""
@ -481,10 +511,14 @@ msgstr "仅修改你需要更新的字段"
#: assets/views/admin_user.py:63 assets/views/admin_user.py:78 #: assets/views/admin_user.py:63 assets/views/admin_user.py:78
#: assets/views/admin_user.py:102 assets/views/asset.py:48 #: assets/views/admin_user.py:102 assets/views/asset.py:48
#: assets/views/asset.py:94 assets/views/asset.py:154 assets/views/asset.py:171 #: assets/views/asset.py:94 assets/views/asset.py:154 assets/views/asset.py:171
#: assets/views/asset.py:195 assets/views/label.py:26 assets/views/label.py:42 #: assets/views/asset.py:195 assets/views/domain.py:29
#: assets/views/label.py:58 assets/views/system_user.py:28 #: assets/views/domain.py:45 assets/views/domain.py:61
#: assets/views/system_user.py:44 assets/views/system_user.py:60 #: assets/views/domain.py:74 assets/views/domain.py:98
#: assets/views/system_user.py:74 templates/_nav.html:20 #: assets/views/domain.py:126 assets/views/domain.py:150
#: assets/views/label.py:26 assets/views/label.py:42 assets/views/label.py:58
#: assets/views/system_user.py:28 assets/views/system_user.py:44
#: assets/views/system_user.py:60 assets/views/system_user.py:74
#: templates/_nav.html:20
msgid "Assets" msgid "Assets"
msgstr "资产管理" msgstr "资产管理"
@ -555,7 +589,7 @@ msgstr "激活中"
#: assets/templates/assets/asset_detail.html:359 #: assets/templates/assets/asset_detail.html:359
#: assets/templates/assets/asset_list.html:90 #: assets/templates/assets/asset_list.html:90
#: assets/templates/assets/system_user_asset.html:52 #: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/system_user_list.html:29 #: assets/templates/assets/system_user_list.html:30
#: users/templates/users/user_granted_asset.html:47 #: users/templates/users/user_granted_asset.html:47
#: users/templates/users/user_group_granted_asset.html:47 #: users/templates/users/user_group_granted_asset.html:47
msgid "Reachable" msgid "Reachable"
@ -564,8 +598,10 @@ msgstr "可连接"
#: assets/templates/assets/_asset_list_modal.html:25 #: assets/templates/assets/_asset_list_modal.html:25
#: assets/templates/assets/admin_user_list.html:30 #: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/asset_list.html:91 #: assets/templates/assets/asset_list.html:91
#: assets/templates/assets/domain_gateway_list.html:62
#: assets/templates/assets/domain_list.html:18
#: assets/templates/assets/label_list.html:17 #: assets/templates/assets/label_list.html:17
#: assets/templates/assets/system_user_list.html:33 #: assets/templates/assets/system_user_list.html:34
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:61 #: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:61
#: ops/templates/ops/task_history.html:62 ops/templates/ops/task_list.html:41 #: ops/templates/ops/task_history.html:62 ops/templates/ops/task_list.html:41
#: perms/templates/perms/asset_permission_list.html:72 #: perms/templates/perms/asset_permission_list.html:72
@ -604,9 +640,11 @@ msgstr "激活所选"
#: assets/templates/assets/_system_user.html:71 #: assets/templates/assets/_system_user.html:71
#: assets/templates/assets/admin_user_create_update.html:46 #: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/asset_bulk_update.html:24 #: assets/templates/assets/asset_bulk_update.html:24
#: assets/templates/assets/asset_create.html:66 #: assets/templates/assets/asset_create.html:67
#: assets/templates/assets/asset_list.html:108 #: assets/templates/assets/asset_list.html:108
#: assets/templates/assets/asset_update.html:70 #: assets/templates/assets/asset_update.html:71
#: assets/templates/assets/domain_create_update.html:17
#: assets/templates/assets/gateway_create_update.html:59
#: assets/templates/assets/label_create_update.html:17 #: assets/templates/assets/label_create_update.html:17
#: common/templates/common/basic_setting.html:59 #: common/templates/common/basic_setting.html:59
#: common/templates/common/email_setting.html:60 #: common/templates/common/email_setting.html:60
@ -631,9 +669,13 @@ msgstr "提交"
#: assets/templates/assets/admin_user_list.html:85 #: assets/templates/assets/admin_user_list.html:85
#: assets/templates/assets/asset_detail.html:24 #: assets/templates/assets/asset_detail.html:24
#: assets/templates/assets/asset_list.html:168 #: assets/templates/assets/asset_list.html:168
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_gateway_list.html:90
#: assets/templates/assets/domain_list.html:38
#: assets/templates/assets/label_list.html:38 #: assets/templates/assets/label_list.html:38
#: assets/templates/assets/system_user_detail.html:26 #: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:87 #: assets/templates/assets/system_user_list.html:88
#: perms/templates/perms/asset_permission_detail.html:30 #: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:121 #: perms/templates/perms/asset_permission_list.html:121
#: terminal/templates/terminal/terminal_detail.html:16 #: terminal/templates/terminal/terminal_detail.html:16
@ -652,9 +694,13 @@ msgstr "更新"
#: assets/templates/assets/admin_user_list.html:86 #: assets/templates/assets/admin_user_list.html:86
#: assets/templates/assets/asset_detail.html:28 #: assets/templates/assets/asset_detail.html:28
#: assets/templates/assets/asset_list.html:169 #: assets/templates/assets/asset_list.html:169
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_gateway_list.html:91
#: assets/templates/assets/domain_list.html:39
#: assets/templates/assets/label_list.html:39 #: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:30 #: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:88 #: assets/templates/assets/system_user_list.html:89
#: ops/templates/ops/task_list.html:71 #: ops/templates/ops/task_list.html:71
#: perms/templates/perms/asset_permission_detail.html:34 #: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:122 #: perms/templates/perms/asset_permission_list.html:122
@ -670,13 +716,15 @@ msgstr "删除"
#: assets/templates/assets/_system_user.html:37 #: assets/templates/assets/_system_user.html:37
#: assets/templates/assets/asset_create.html:16 #: assets/templates/assets/asset_create.html:16
#: assets/templates/assets/asset_update.html:21 #: assets/templates/assets/asset_update.html:21
#: assets/templates/assets/gateway_create_update.html:37
#: perms/templates/perms/asset_permission_create_update.html:38 #: perms/templates/perms/asset_permission_create_update.html:38
msgid "Basic" msgid "Basic"
msgstr "基本" msgstr "基本"
#: assets/templates/assets/_system_user.html:44 #: assets/templates/assets/_system_user.html:44
#: assets/templates/assets/asset_create.html:24 #: assets/templates/assets/asset_create.html:25
#: assets/templates/assets/asset_update.html:29 #: assets/templates/assets/asset_update.html:30
#: assets/templates/assets/gateway_create_update.html:45
#: assets/templates/assets/system_user_update.html:7 #: assets/templates/assets/system_user_update.html:7
#: users/templates/users/user_create.html:9 #: users/templates/users/user_create.html:9
#: users/templates/users/user_update.html:6 #: users/templates/users/user_update.html:6
@ -688,8 +736,9 @@ msgid "Auto generate key"
msgstr "自动生成密钥" msgstr "自动生成密钥"
#: assets/templates/assets/_system_user.html:64 #: assets/templates/assets/_system_user.html:64
#: assets/templates/assets/asset_create.html:58 #: assets/templates/assets/asset_create.html:59
#: assets/templates/assets/asset_update.html:62 #: assets/templates/assets/asset_update.html:63
#: assets/templates/assets/gateway_create_update.html:53
#: perms/templates/perms/asset_permission_create_update.html:49 #: perms/templates/perms/asset_permission_create_update.html:49
#: terminal/templates/terminal/terminal_update.html:42 #: terminal/templates/terminal/terminal_update.html:42
msgid "Other" msgid "Other"
@ -698,8 +747,10 @@ msgstr "其它"
#: assets/templates/assets/_system_user.html:70 #: assets/templates/assets/_system_user.html:70
#: assets/templates/assets/admin_user_create_update.html:45 #: assets/templates/assets/admin_user_create_update.html:45
#: assets/templates/assets/asset_bulk_update.html:23 #: assets/templates/assets/asset_bulk_update.html:23
#: assets/templates/assets/asset_create.html:65 #: assets/templates/assets/asset_create.html:66
#: assets/templates/assets/asset_update.html:69 #: assets/templates/assets/asset_update.html:70
#: assets/templates/assets/domain_create_update.html:16
#: assets/templates/assets/gateway_create_update.html:58
#: assets/templates/assets/label_create_update.html:16 #: assets/templates/assets/label_create_update.html:16
#: common/templates/common/basic_setting.html:58 #: common/templates/common/basic_setting.html:58
#: common/templates/common/email_setting.html:59 #: common/templates/common/email_setting.html:59
@ -719,6 +770,8 @@ msgstr "重置"
#: assets/templates/assets/admin_user_assets.html:18 #: assets/templates/assets/admin_user_assets.html:18
#: assets/templates/assets/admin_user_detail.html:18 #: assets/templates/assets/admin_user_detail.html:18
#: assets/templates/assets/domain_detail.html:18
#: assets/templates/assets/domain_gateway_list.html:18
#: assets/templates/assets/system_user_asset.html:17 #: assets/templates/assets/system_user_asset.html:17
#: assets/templates/assets/system_user_detail.html:18 #: assets/templates/assets/system_user_detail.html:18
#: ops/templates/ops/adhoc_history.html:129 #: ops/templates/ops/adhoc_history.html:129
@ -771,7 +824,7 @@ msgstr "替换资产的管理员"
#: assets/templates/assets/asset_detail.html:200 #: assets/templates/assets/asset_detail.html:200
#: assets/templates/assets/asset_list.html:586 #: assets/templates/assets/asset_list.html:586
#: assets/templates/assets/system_user_detail.html:183 #: assets/templates/assets/system_user_detail.html:183
#: assets/templates/assets/system_user_list.html:137 templates/_modal.html:16 #: assets/templates/assets/system_user_list.html:138 templates/_modal.html:16
#: terminal/templates/terminal/session_detail.html:108 #: terminal/templates/terminal/session_detail.html:108
#: users/templates/users/user_detail.html:339 #: users/templates/users/user_detail.html:339
#: users/templates/users/user_detail.html:364 #: users/templates/users/user_detail.html:364
@ -789,27 +842,27 @@ msgid "Create admin user"
msgstr "创建管理用户" msgstr "创建管理用户"
#: assets/templates/assets/admin_user_list.html:27 #: assets/templates/assets/admin_user_list.html:27
#: assets/templates/assets/system_user_list.html:30 #: assets/templates/assets/system_user_list.html:31
msgid "Unreachable" msgid "Unreachable"
msgstr "不可达" msgstr "不可达"
#: assets/templates/assets/admin_user_list.html:28 #: assets/templates/assets/admin_user_list.html:28
#: assets/templates/assets/system_user_list.html:31 #: assets/templates/assets/system_user_list.html:32
#: ops/templates/ops/adhoc_history.html:54 #: ops/templates/ops/adhoc_history.html:54
#: ops/templates/ops/task_history.html:57 #: ops/templates/ops/task_history.html:57
msgid "Ratio" msgid "Ratio"
msgstr "比例" msgstr "比例"
#: assets/templates/assets/asset_create.html:28 #: assets/templates/assets/asset_create.html:29
#: assets/templates/assets/asset_update.html:33 perms/models.py:74 #: assets/templates/assets/asset_update.html:34 perms/models.py:74
#: perms/templates/perms/asset_permission_create_update.html:40 #: perms/templates/perms/asset_permission_create_update.html:40
#: perms/templates/perms/asset_permission_list.html:67 #: perms/templates/perms/asset_permission_list.html:67
msgid "Node" msgid "Node"
msgstr "节点" msgstr "节点"
#: assets/templates/assets/asset_create.html:34 #: assets/templates/assets/asset_create.html:35
#: assets/templates/assets/asset_list.html:75 #: assets/templates/assets/asset_list.html:75
#: assets/templates/assets/asset_update.html:39 #: assets/templates/assets/asset_update.html:40
msgid "Label" msgid "Label"
msgstr "标签" msgstr "标签"
@ -903,7 +956,7 @@ msgid "Have child node, cancel"
msgstr "存在子节点,不能删除" msgstr "存在子节点,不能删除"
#: assets/templates/assets/asset_list.html:581 #: assets/templates/assets/asset_list.html:581
#: assets/templates/assets/system_user_list.html:132 #: assets/templates/assets/system_user_list.html:133
#: users/templates/users/user_detail.html:334 #: users/templates/users/user_detail.html:334
#: users/templates/users/user_detail.html:359 #: users/templates/users/user_detail.html:359
#: users/templates/users/user_group_list.html:81 #: users/templates/users/user_group_list.html:81
@ -928,7 +981,7 @@ msgstr "删除"
msgid "Asset Deleting failed." msgid "Asset Deleting failed."
msgstr "删除失败" msgstr "删除失败"
#: assets/templates/assets/asset_update.html:58 #: assets/templates/assets/asset_update.html:59
msgid "Configuration" msgid "Configuration"
msgstr "配置" msgstr "配置"
@ -942,6 +995,32 @@ msgstr "确认删除"
msgid "Are you sure delete" msgid "Are you sure delete"
msgstr "您确定删除吗?" msgstr "您确定删除吗?"
#: assets/templates/assets/domain_detail.html:21
#: assets/templates/assets/domain_detail.html:64
#: assets/templates/assets/domain_gateway_list.html:21
#: assets/templates/assets/domain_list.html:16
msgid "Gateway"
msgstr "网关"
#: assets/templates/assets/domain_gateway_list.html:31
msgid "Gateway list"
msgstr "网关列表"
#: assets/templates/assets/domain_gateway_list.html:48
#: assets/views/domain.py:127
msgid "Create gateway"
msgstr "创建网关"
#: assets/templates/assets/domain_gateway_list.html:92
#: common/templates/common/email_setting.html:58
#: common/templates/common/ldap_setting.html:58
msgid "Test connection"
msgstr "测试连接"
#: assets/templates/assets/domain_list.html:6 assets/views/domain.py:46
msgid "Create domain"
msgstr "创建网域"
#: assets/templates/assets/label_list.html:6 assets/views/label.py:43 #: assets/templates/assets/label_list.html:6 assets/views/label.py:43
msgid "Create label" msgid "Create label"
msgstr "创建标签" msgstr "创建标签"
@ -992,20 +1071,20 @@ msgstr "添加到节点"
msgid "Create system user" msgid "Create system user"
msgstr "创建系统用户" msgstr "创建系统用户"
#: assets/templates/assets/system_user_list.html:133 #: assets/templates/assets/system_user_list.html:134
msgid "This will delete the selected System Users !!!" msgid "This will delete the selected System Users !!!"
msgstr "删除选择系统用户" msgstr "删除选择系统用户"
#: assets/templates/assets/system_user_list.html:141 #: assets/templates/assets/system_user_list.html:142
msgid "System Users Deleted." msgid "System Users Deleted."
msgstr "已被删除" msgstr "已被删除"
#: assets/templates/assets/system_user_list.html:142 #: assets/templates/assets/system_user_list.html:143
#: assets/templates/assets/system_user_list.html:147 #: assets/templates/assets/system_user_list.html:148
msgid "System Users Delete" msgid "System Users Delete"
msgstr "删除系统用户" msgstr "删除系统用户"
#: assets/templates/assets/system_user_list.html:146 #: assets/templates/assets/system_user_list.html:147
msgid "System Users Deleting failed." msgid "System Users Deleting failed."
msgstr "系统用户删除失败" msgstr "系统用户删除失败"
@ -1045,6 +1124,26 @@ msgstr "更新资产"
msgid "already exists" msgid "already exists"
msgstr "已经存在" msgstr "已经存在"
#: assets/views/domain.py:30 templates/_nav.html:24
msgid "Domain list"
msgstr "网域列表"
#: assets/views/domain.py:62
msgid "Update domain"
msgstr "更新网域"
#: assets/views/domain.py:75
msgid "Domain detail"
msgstr "网域详情"
#: assets/views/domain.py:99
msgid "Domain gateway list"
msgstr "域网关列表"
#: assets/views/domain.py:151
msgid "Update gateway"
msgstr "创建网关"
#: assets/views/label.py:27 #: assets/views/label.py:27
msgid "Label list" msgid "Label list"
msgstr "标签列表" msgstr "标签列表"
@ -1275,11 +1374,6 @@ msgstr "LDAP设置"
msgid "Terminal setting" msgid "Terminal setting"
msgstr "终端设置" msgstr "终端设置"
#: common/templates/common/email_setting.html:58
#: common/templates/common/ldap_setting.html:58
msgid "Test connection"
msgstr "测试连接"
#: common/templates/common/terminal_setting.html:68 #: common/templates/common/terminal_setting.html:68
#: common/templates/common/terminal_setting.html:86 #: common/templates/common/terminal_setting.html:86
#: users/templates/users/login_log_list.html:50 #: users/templates/users/login_log_list.html:50
@ -1287,7 +1381,7 @@ msgid "Type"
msgstr "类型" msgstr "类型"
#: common/views.py:20 common/views.py:46 common/views.py:72 common/views.py:102 #: common/views.py:20 common/views.py:46 common/views.py:72 common/views.py:102
#: templates/_nav.html:72 #: templates/_nav.html:73
msgid "Settings" msgid "Settings"
msgstr "系统设置" msgstr "系统设置"
@ -1554,7 +1648,7 @@ msgstr "任务开始: "
msgid "Ops" msgid "Ops"
msgstr "作业中心" msgstr "作业中心"
#: ops/views.py:37 templates/_nav.html:58 #: ops/views.py:37 templates/_nav.html:59
msgid "Task list" msgid "Task list"
msgstr "任务列表" msgstr "任务列表"
@ -1579,7 +1673,7 @@ msgstr "用户组"
msgid "Date expired" msgid "Date expired"
msgstr "失效日期" msgstr "失效日期"
#: perms/models.py:88 templates/_nav.html:33 #: perms/models.py:88 templates/_nav.html:34
msgid "Asset permission" msgid "Asset permission"
msgstr "资产授权" msgstr "资产授权"
@ -1669,7 +1763,7 @@ msgstr "添加用户组"
msgid "Select user groups" msgid "Select user groups"
msgstr "选择用户组" msgstr "选择用户组"
#: perms/views.py:23 perms/views.py:47 perms/views.py:67 templates/_nav.html:30 #: perms/views.py:23 perms/views.py:47 perms/views.py:67 templates/_nav.html:31
msgid "Perms" msgid "Perms"
msgstr "权限管理" msgstr "权限管理"
@ -1770,27 +1864,27 @@ msgstr "用户列表"
msgid "Login logs" msgid "Login logs"
msgstr "登录日志" msgstr "登录日志"
#: templates/_nav.html:39 #: templates/_nav.html:40
msgid "Sessions" msgid "Sessions"
msgstr "会话管理" msgstr "会话管理"
#: templates/_nav.html:42 #: templates/_nav.html:43
msgid "Session online" msgid "Session online"
msgstr "在线会话" msgstr "在线会话"
#: templates/_nav.html:43 #: templates/_nav.html:44
msgid "Session offline" msgid "Session offline"
msgstr "历史会话" msgstr "历史会话"
#: templates/_nav.html:44 #: templates/_nav.html:45
msgid "Commands" msgid "Commands"
msgstr "命令记录" msgstr "命令记录"
#: templates/_nav.html:47 templates/_nav_user.html:14 #: templates/_nav.html:48 templates/_nav_user.html:14
msgid "Web terminal" msgid "Web terminal"
msgstr "Web终端" msgstr "Web终端"
#: templates/_nav.html:50 terminal/templates/terminal/session_list.html:75 #: templates/_nav.html:51 terminal/templates/terminal/session_list.html:75
#: terminal/views/command.py:47 terminal/views/session.py:75 #: terminal/views/command.py:47 terminal/views/session.py:75
#: terminal/views/session.py:93 terminal/views/session.py:115 #: terminal/views/session.py:93 terminal/views/session.py:115
#: terminal/views/terminal.py:31 terminal/views/terminal.py:46 #: terminal/views/terminal.py:31 terminal/views/terminal.py:46
@ -1798,7 +1892,7 @@ msgstr "Web终端"
msgid "Terminal" msgid "Terminal"
msgstr "终端管理" msgstr "终端管理"
#: templates/_nav.html:55 #: templates/_nav.html:56
msgid "Job Center" msgid "Job Center"
msgstr "作业中心" msgstr "作业中心"
@ -2684,62 +2778,3 @@ msgstr "密码更新"
msgid "Public key update" msgid "Public key update"
msgstr "密钥更新" msgstr "密钥更新"
#~ msgid "If auto push checked, system user will be create at node assets"
#~ msgstr "如果选择了自动推送,系统用户将会创建在节点资产上"
#~ msgid "First step"
#~ msgstr "第一步"
#~ msgid "Prev step"
#~ msgstr "上一步"
#~ msgid "Test node assets connective: {}"
#~ msgstr "测试节点资产可连接性"
#~ msgid ""
#~ "Admin user is a privilege user exist on this asset,Example: root or other "
#~ "NOPASSWD sudo privilege userIf asset not support ansible, set any one"
#~ msgstr ""
#~ "管理用户是资产上已经存在的特权用户,如 root或者其它有NOPASSWD的用户, 如果"
#~ "资产是Windows或交换机, 任意设置一个即可"
#~ msgid "Refresh node assets hardware info: {}"
#~ msgstr "更新一些资产硬件信息: {}"
#~ msgid "Update some assets hardware info"
#~ msgstr "更新一些资产硬件信息"
#~ msgid "Update asset hardware info"
#~ msgstr "更新资产硬件信息"
#~ msgid "Update assets hardware info period"
#~ msgstr "定期更新资产硬件信息"
#~ msgid "Test admin user connectability period: {}"
#~ msgstr "定期测试管理用户可连接性: {}"
#~ msgid "Test admin user connectability: {}"
#~ msgstr "测试管理用户可连接性: {}"
#, fuzzy
#~| msgid "Test asset connectability"
#~ msgid "Test assets connectability"
#~ msgstr "测试资产可连接性"
#~ msgid "Test system user connectability period: {}"
#~ msgstr "测试系统用户可连接性: {}"
#~ msgid "Push system user to node: {} => {}"
#~ msgstr "推送系统用户到节点: {}->{}"
#~ msgid "Push system users to node: {}"
#~ msgstr "推送系统用户到节点: {}"
#~ msgid "Coco ssh listen port"
#~ msgstr "SSH 监听端口"
#~ msgid "Coco http/ws listen port"
#~ msgstr "Http/Websocket 监听端口"
#~ msgid "Create asset permission "
#~ msgstr "创建资产权限"

View File

@ -29,6 +29,7 @@ class BaseHost(Host):
} }
"groups": [], "groups": [],
"vars": {}, "vars": {},
"other_ansbile_vars":
} }
""" """
self.host_data = host_data self.host_data = host_data

View File

@ -9,6 +9,23 @@ __all__ = [
] ]
def make_proxy_command(asset):
gateway = asset.domain.random_gateway()
proxy_command = [
"ssh", "-p", str(gateway.port),
"{}@{}".format(gateway.username, gateway.ip),
"-W", "%h:%p", "-q",
]
if gateway.password:
proxy_command.insert(0, "sshpass -p {}".format(gateway.password))
if gateway.private_key:
proxy_command.append("-i {}".format(gateway.private_key_file))
return {"ansible_ssh_common_args": "'-o ProxyCommand={}'".format(" ".join(proxy_command))}
class JMSInventory(BaseInventory): class JMSInventory(BaseInventory):
""" """
JMS Inventory is the manager with jumpserver assets, so you can JMS Inventory is the manager with jumpserver assets, so you can
@ -21,17 +38,29 @@ class JMSInventory(BaseInventory):
self.become_info = become_info self.become_info = become_info
assets = self.get_jms_assets() assets = self.get_jms_assets()
if run_as_admin: host_list = []
host_list = [asset._to_secret_json() for asset in assets]
else: for asset in assets:
host_list = [asset.to_json() for asset in assets] vars = {}
if run_as: if run_as_admin:
run_user_info = self.get_run_user_info() info = asset._to_secret_json()
for host in host_list: else:
host.update(run_user_info) info = asset.to_json()
if become_info:
for host in host_list: info["vars"] = vars
host.update(become_info) if asset.domain and asset.domain.has_gateway():
vars.update(make_proxy_command(asset))
info.update(vars)
host_list.append(info)
if run_as:
run_user_info = self.get_run_user_info()
for host in host_list:
host.update(run_user_info)
if become_info:
for host in host_list:
host.update(become_info)
super().__init__(host_list=host_list) super().__init__(host_list=host_list)
def get_jms_assets(self): def get_jms_assets(self):

View File

@ -3,7 +3,7 @@
from users.utils import AdminUserRequiredMixin from users.utils import AdminUserRequiredMixin
from users.models import User, UserGroup from users.models import User, UserGroup
from assets.models import Asset, AssetGroup, SystemUser, Node from assets.models import Asset, SystemUser, Node
from assets.serializers import AssetGrantedSerializer, NodeGrantedSerializer, NodeSerializer from assets.serializers import AssetGrantedSerializer, NodeGrantedSerializer, NodeSerializer

View File

@ -205,6 +205,7 @@ function objectDelete(obj, name, url, redirectTo) {
url: url, url: url,
body: JSON.stringify(body), body: JSON.stringify(body),
method: 'DELETE', method: 'DELETE',
success_message: "删除成功",
success: success, success: success,
error: fail error: fail
}); });

File diff suppressed because one or more lines are too long

View File

@ -21,6 +21,7 @@
</a> </a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset list' %}</a></li> <li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset list' %}</a></li>
<li id="domain"><a href="{% url 'assets:domain-list' %}">{% trans 'Domain list' %}</a></li>
<li id="admin-user"><a href="{% url 'assets:admin-user-list' %}">{% trans 'Admin user' %}</a></li> <li id="admin-user"><a href="{% url 'assets:admin-user-list' %}">{% trans 'Admin user' %}</a></li>
<li id="system-user"><a href="{% url 'assets:system-user-list' %}">{% trans 'System user' %}</a></li> <li id="system-user"><a href="{% url 'assets:system-user-list' %}">{% trans 'System user' %}</a></li>
<li id="label"><a href="{% url 'assets:label-list' %}">{% trans 'Labels' %}</a></li> <li id="label"><a href="{% url 'assets:label-list' %}">{% trans 'Labels' %}</a></li>

5
jms
View File

@ -80,14 +80,13 @@ def get_log_file_path(service):
def get_pid(service): def get_pid(service):
pid_file = get_pid_file_path(service) pid_file = get_pid_file_path(service)
pid = 0
if os.path.isfile(pid_file): if os.path.isfile(pid_file):
with open(pid_file) as f: with open(pid_file) as f:
try: try:
return int(f.read().strip()) return int(f.read().strip())
except ValueError: except ValueError:
pass return 0
return pid return 0
def is_running(s, unlink=True): def is_running(s, unlink=True):