mirror of https://github.com/jumpserver/jumpserver
[Change] 修改idc => cluster
parent
32fd9bb42f
commit
27a1849b1d
|
@ -24,7 +24,7 @@ from common.mixins import IDInFilterMixin
|
|||
from common.utils import get_object_or_none
|
||||
from .hands import IsSuperUser, IsAppUser, IsValidUser, \
|
||||
get_user_granted_assets, push_users
|
||||
from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser
|
||||
from .models import AssetGroup, Asset, Cluster, SystemUser, AdminUser
|
||||
from . import serializers
|
||||
from .tasks import update_assets_hardware_info
|
||||
from .utils import test_admin_user_connective_manual
|
||||
|
@ -41,12 +41,12 @@ class AssetViewSet(IDInFilterMixin, BulkModelViewSet):
|
|||
queryset = super(AssetViewSet, self).get_queryset()
|
||||
else:
|
||||
queryset = get_user_granted_assets(self.request.user)
|
||||
idc_id = self.request.query_params.get('idc_id', '')
|
||||
cluster_id = self.request.query_params.get('cluster_id', '')
|
||||
system_users_id = self.request.query_params.get('system_user_id', '')
|
||||
asset_group_id = self.request.query_params.get('asset_group_id', '')
|
||||
admin_user_id = self.request.query_params.get('admin_user_id', '')
|
||||
if idc_id:
|
||||
queryset = queryset.filter(idc__id=idc_id)
|
||||
if cluster_id:
|
||||
queryset = queryset.filter(cluster__id=cluster_id)
|
||||
if system_users_id:
|
||||
queryset = queryset.filter(system_users__id=system_users_id)
|
||||
if admin_user_id:
|
||||
|
@ -84,17 +84,17 @@ class AssetGroupUpdateSystemUserApi(generics.RetrieveUpdateAPIView):
|
|||
permission_classes = (IsSuperUser,)
|
||||
|
||||
|
||||
class IDCUpdateAssetsApi(generics.RetrieveUpdateAPIView):
|
||||
"""IDC update asset member"""
|
||||
queryset = IDC.objects.all()
|
||||
serializer_class = serializers.IDCUpdateAssetsSerializer
|
||||
class ClusterUpdateAssetsApi(generics.RetrieveUpdateAPIView):
|
||||
"""Cluster update asset member"""
|
||||
queryset = Cluster.objects.all()
|
||||
serializer_class = serializers.ClusterUpdateAssetsSerializer
|
||||
permission_classes = (IsSuperUser,)
|
||||
|
||||
|
||||
class IDCViewSet(IDInFilterMixin, BulkModelViewSet):
|
||||
"""IDC api set, for add,delete,update,list,retrieve resource"""
|
||||
queryset = IDC.objects.all()
|
||||
serializer_class = serializers.IDCSerializer
|
||||
class ClusterViewSet(IDInFilterMixin, BulkModelViewSet):
|
||||
"""Cluster api set, for add,delete,update,list,retrieve resource"""
|
||||
queryset = Cluster.objects.all()
|
||||
serializer_class = serializers.ClusterSerializer
|
||||
permission_classes = (IsSuperUser,)
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import IDC, Asset, AssetGroup, AdminUser, SystemUser
|
||||
from .models import Cluster, Asset, AssetGroup, AdminUser, SystemUser
|
||||
from common.utils import validate_ssh_private_key, ssh_pubkey_gen, ssh_key_gen, get_logger
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@ class AssetCreateForm(forms.ModelForm):
|
|||
model = Asset
|
||||
fields = [
|
||||
'hostname', 'ip', 'public_ip', 'port', 'type', 'comment',
|
||||
'admin_user', 'idc', 'groups', 'status', 'env', 'is_active'
|
||||
'admin_user', "cluster", 'groups', 'status', 'env', 'is_active'
|
||||
]
|
||||
widgets = {
|
||||
'groups': forms.SelectMultiple(
|
||||
|
@ -43,7 +43,7 @@ class AssetUpdateForm(forms.ModelForm):
|
|||
class Meta:
|
||||
model = Asset
|
||||
fields = [
|
||||
'hostname', 'ip', 'port', 'groups', 'admin_user', 'idc', 'is_active',
|
||||
'hostname', 'ip', 'port', 'groups', 'admin_user', "cluster", 'is_active',
|
||||
'type', 'env', 'status', 'public_ip', 'remote_card_ip', 'cabinet_no',
|
||||
'cabinet_pos', 'number', 'comment'
|
||||
]
|
||||
|
@ -83,7 +83,7 @@ class AssetBulkUpdateForm(forms.ModelForm):
|
|||
class Meta:
|
||||
model = Asset
|
||||
fields = [
|
||||
'assets', 'port', 'groups', 'admin_user', 'idc',
|
||||
'assets', 'port', 'groups', 'admin_user', "cluster",
|
||||
'type', 'env', 'status',
|
||||
]
|
||||
widgets = {
|
||||
|
@ -139,7 +139,7 @@ class AssetGroupForm(forms.ModelForm):
|
|||
}
|
||||
|
||||
|
||||
class IDCForm(forms.ModelForm):
|
||||
class ClusterForm(forms.ModelForm):
|
||||
# See AdminUserForm comment same it
|
||||
assets = forms.ModelMultipleChoiceField(
|
||||
queryset=Asset.objects.all(),
|
||||
|
@ -153,16 +153,16 @@ class IDCForm(forms.ModelForm):
|
|||
if kwargs.get('instance'):
|
||||
initial = kwargs.get('initial', {})
|
||||
initial['assets'] = kwargs['instance'].assets.all()
|
||||
super(IDCForm, self).__init__(*args, **kwargs)
|
||||
super(ClusterForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def _save_m2m(self):
|
||||
super(IDCForm, self)._save_m2m()
|
||||
super(ClusterForm, self)._save_m2m()
|
||||
assets = self.cleaned_data['assets']
|
||||
self.instance.assets.clear()
|
||||
self.instance.assets.add(*tuple(assets))
|
||||
|
||||
class Meta:
|
||||
model = IDC
|
||||
model = Cluster
|
||||
fields = ['name', "bandwidth", "operator", 'contact',
|
||||
'phone', 'address', 'intranet', 'extranet', 'comment']
|
||||
widgets = {
|
||||
|
@ -356,6 +356,5 @@ class SystemUserUpdateForm(forms.ModelForm):
|
|||
}
|
||||
|
||||
|
||||
|
||||
class FileForm(forms.Form):
|
||||
file = forms.FileField()
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from .idc import *
|
||||
from .cluster import *
|
||||
from .user import *
|
||||
from .group import *
|
||||
from .asset import *
|
||||
|
|
|
@ -10,14 +10,14 @@ from django.db import models
|
|||
import logging
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from . import IDC, AssetGroup, AdminUser, SystemUser
|
||||
from . import Cluster, AssetGroup, AdminUser, SystemUser
|
||||
|
||||
__all__ = ['Asset']
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_default_idc():
|
||||
return IDC.initial()
|
||||
def get_default_cluster():
|
||||
return Cluster.initial()
|
||||
|
||||
|
||||
class Asset(models.Model):
|
||||
|
@ -47,7 +47,7 @@ class Asset(models.Model):
|
|||
groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets', verbose_name=_('Asset groups'))
|
||||
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, related_name='assets', on_delete=models.SET_NULL, verbose_name=_("Admin user"))
|
||||
system_users = models.ManyToManyField(SystemUser, blank=True, related_name='assets', verbose_name=_("System User"))
|
||||
idc = models.ForeignKey(IDC, blank=True, null=True, related_name='assets', on_delete=models.SET_NULL, verbose_name=_('IDC'),)
|
||||
cluster = models.ForeignKey(Cluster, blank=True, null=True, related_name='assets', on_delete=models.SET_NULL, verbose_name=_('Cluster'),)
|
||||
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
||||
type = models.CharField(choices=TYPE_CHOICES, max_length=16, blank=True, null=True, default='Server', verbose_name=_('Asset type'),)
|
||||
env = models.CharField(choices=ENV_CHOICES, max_length=8, blank=True, null=True, default='Prod', verbose_name=_('Asset environment'),)
|
||||
|
@ -100,18 +100,16 @@ class Asset(models.Model):
|
|||
'hostname': self.hostname,
|
||||
'ip': self.ip,
|
||||
'port': self.port,
|
||||
}
|
||||
|
||||
def _to_secret_json(self):
|
||||
"""Ansible use it create inventory"""
|
||||
data = {
|
||||
'id': self.id,
|
||||
'hostname': self.hostname,
|
||||
'ip': self.ip,
|
||||
'port': self.port,
|
||||
'groups': [group.name for group in self.groups.all()],
|
||||
}
|
||||
|
||||
def _to_secret_json(self):
|
||||
"""
|
||||
Ansible use it create inventory
|
||||
|
||||
Todo: May be move to ops implements it
|
||||
"""
|
||||
data = self.to_json()
|
||||
if self.admin_user:
|
||||
data.update({
|
||||
'username': self.admin_user.username,
|
||||
|
@ -139,7 +137,7 @@ class Asset(models.Model):
|
|||
asset = cls(ip='%s.%s.%s.%s' % (i, i, i, i),
|
||||
hostname=forgery_py.internet.user_name(True),
|
||||
admin_user=choice(AdminUser.objects.all()),
|
||||
idc=choice(IDC.objects.all()),
|
||||
cluster=choice(Cluster.objects.all()),
|
||||
port=22,
|
||||
created_by='Fake')
|
||||
try:
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
__all__ = ['Cluster']
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Cluster(models.Model):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=32, verbose_name=_('Name'))
|
||||
bandwidth = models.CharField(max_length=32, blank=True, verbose_name=_('Bandwidth'))
|
||||
contact = models.CharField(max_length=128, blank=True, verbose_name=_('Contact'))
|
||||
phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone'))
|
||||
address = models.CharField(max_length=128, blank=True, verbose_name=_("Address"))
|
||||
intranet = models.TextField(blank=True, verbose_name=_('Intranet'))
|
||||
extranet = models.TextField(blank=True, verbose_name=_('Extranet'))
|
||||
date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date created'))
|
||||
operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator'))
|
||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
def initial(cls):
|
||||
return cls.objects.get_or_create(name=_('Default'), created_by=_('System'), comment=_('Default Cluster'))[0]
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
|
||||
@classmethod
|
||||
def generate_fake(cls, count=5):
|
||||
from random import seed, choice
|
||||
import forgery_py
|
||||
from django.db import IntegrityError
|
||||
|
||||
seed()
|
||||
for i in range(count):
|
||||
cluster = cls(name=forgery_py.name.full_name(),
|
||||
bandwidth='200M',
|
||||
contact=forgery_py.name.full_name(),
|
||||
phone=forgery_py.address.phone(),
|
||||
address=forgery_py.address.city() + forgery_py.address.street_address(),
|
||||
operator=choice(['北京联通', '北京电信', 'BGP全网通']),
|
||||
comment=forgery_py.lorem_ipsum.sentence(),
|
||||
created_by='Fake')
|
||||
try:
|
||||
cluster.save()
|
||||
logger.debug('Generate fake asset group: %s' % cluster.name)
|
||||
except IntegrityError:
|
||||
print('Error continue')
|
||||
continue
|
|
@ -1,71 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
__all__ = ['IDC']
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class IDC(models.Model):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=32, verbose_name=_('Name'))
|
||||
bandwidth = models.CharField(
|
||||
max_length=32, blank=True, verbose_name=_('Bandwidth'))
|
||||
contact = models.CharField(
|
||||
max_length=128, blank=True, verbose_name=_('Contact'))
|
||||
phone = models.CharField(max_length=32, blank=True,
|
||||
verbose_name=_('Phone'))
|
||||
address = models.CharField(
|
||||
max_length=128, blank=True, verbose_name=_("Address"))
|
||||
intranet = models.TextField(blank=True, verbose_name=_('Intranet'))
|
||||
extranet = models.TextField(blank=True, verbose_name=_('Extranet'))
|
||||
date_created = models.DateTimeField(
|
||||
auto_now_add=True, null=True, verbose_name=_('Date created'))
|
||||
operator = models.CharField(
|
||||
max_length=32, blank=True, verbose_name=_('Operator'))
|
||||
created_by = models.CharField(
|
||||
max_length=32, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
__str__ = __unicode__
|
||||
|
||||
@classmethod
|
||||
def initial(cls):
|
||||
return cls.objects.get_or_create(name=_('Default'), created_by=_('System'), comment=_('Default IDC'))[0]
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
|
||||
@classmethod
|
||||
def generate_fake(cls, count=5):
|
||||
from random import seed, choice
|
||||
import forgery_py
|
||||
from django.db import IntegrityError
|
||||
|
||||
seed()
|
||||
for i in range(count):
|
||||
idc = cls(name=forgery_py.name.full_name(),
|
||||
bandwidth='200M',
|
||||
contact=forgery_py.name.full_name(),
|
||||
phone=forgery_py.address.phone(),
|
||||
address=forgery_py.address.city() + forgery_py.address.street_address(),
|
||||
operator=choice(['北京联通', '北京电信', 'BGP全网通']),
|
||||
comment=forgery_py.lorem_ipsum.sentence(),
|
||||
created_by='Fake')
|
||||
try:
|
||||
idc.save()
|
||||
logger.debug('Generate fake asset group: %s' % idc.name)
|
||||
except IntegrityError:
|
||||
print('Error continue')
|
||||
continue
|
|
@ -29,7 +29,7 @@ def private_key_validator(value):
|
|||
|
||||
class AdminUser(models.Model):
|
||||
"""
|
||||
Ansible use admin user as devops user to run adHoc and Playbook
|
||||
A privileged user that ansible can use it to push system user and so on
|
||||
"""
|
||||
BECOME_METHOD_CHOICES = (
|
||||
('sudo', 'sudo'),
|
||||
|
@ -43,7 +43,7 @@ class AdminUser(models.Model):
|
|||
become = models.BooleanField(default=True)
|
||||
become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4)
|
||||
become_user = models.CharField(default='root', max_length=64)
|
||||
become_pass = models.CharField(default='', max_length=128)
|
||||
_become_pass = models.CharField(default='', max_length=128)
|
||||
_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, null=True)
|
||||
|
@ -95,6 +95,15 @@ class AdminUser(models.Model):
|
|||
def public_key(self, public_key_raw):
|
||||
self._public_key = signer.sign(public_key_raw)
|
||||
|
||||
@property
|
||||
def become_pass(self):
|
||||
return signer.unsign(self._become_pass)
|
||||
|
||||
@become_pass.setter
|
||||
def become_pass(self, password):
|
||||
self._become_pass = signer.sign(password)
|
||||
|
||||
|
||||
@property
|
||||
def assets_amount(self):
|
||||
return self.assets.count()
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from . import IDC, SystemUser, AdminUser, AssetGroup, Asset
|
||||
from . import Cluster, SystemUser, AdminUser, AssetGroup, Asset
|
||||
|
||||
__all__ = ['init_model', 'generate_fake']
|
||||
|
||||
|
||||
def init_model():
|
||||
for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset]:
|
||||
for cls in [Cluster, SystemUser, AdminUser, AssetGroup, Asset]:
|
||||
if hasattr(cls, 'initial'):
|
||||
cls.initial()
|
||||
|
||||
|
||||
def generate_fake():
|
||||
for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset]:
|
||||
for cls in [Cluster, SystemUser, AdminUser, AssetGroup, Asset]:
|
||||
if hasattr(cls, 'generate_fake'):
|
||||
cls.generate_fake()
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.cache import cache
|
||||
from rest_framework import viewsets, serializers, generics
|
||||
from .models import AssetGroup, Asset, IDC, AdminUser, SystemUser
|
||||
from .models import AssetGroup, Asset, Cluster, AdminUser, SystemUser
|
||||
from common.mixins import IDInFilterMixin
|
||||
from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin
|
||||
|
||||
|
@ -54,11 +54,11 @@ class AssetGroupUpdateSystemUserSerializer(serializers.ModelSerializer):
|
|||
fields = ['id', 'system_users']
|
||||
|
||||
|
||||
class IDCUpdateAssetsSerializer(serializers.ModelSerializer):
|
||||
class ClusterUpdateAssetsSerializer(serializers.ModelSerializer):
|
||||
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
||||
|
||||
class Meta:
|
||||
model = IDC
|
||||
model = Cluster
|
||||
fields = ['id', 'assets']
|
||||
|
||||
|
||||
|
@ -180,12 +180,12 @@ class MyAssetGrantedSerializer(AssetGrantedSerializer):
|
|||
"is_active", "system_users_join", "comment")
|
||||
|
||||
|
||||
class IDCSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||
class ClusterSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||
assets_amount = serializers.SerializerMethodField()
|
||||
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
||||
|
||||
class Meta:
|
||||
model = IDC
|
||||
model = Cluster
|
||||
fields = '__all__'
|
||||
|
||||
@staticmethod
|
||||
|
@ -193,7 +193,7 @@ class IDCSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
|||
return obj.assets.count()
|
||||
|
||||
def get_field_names(self, declared_fields, info):
|
||||
fields = super(IDCSerializer, self).get_field_names(declared_fields, info)
|
||||
fields = super(ClusterSerializer, self).get_field_names(declared_fields, info)
|
||||
fields.append('assets_amount')
|
||||
return fields
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>{% trans 'Group' %}</h3>
|
||||
{% bootstrap_field form.idc layout="horizontal" %}
|
||||
{% bootstrap_field form.cluster layout="horizontal" %}
|
||||
{% bootstrap_field form.groups layout="horizontal" %}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
|
|
|
@ -82,8 +82,8 @@
|
|||
<td><b>{{ asset.remote_card_ip }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'IDC' %}:</td>
|
||||
<td><b>{{ asset.idc.name }}</b></td>
|
||||
<td>{% trans 'Cluster' %}:</td>
|
||||
<td><b>{{ asset.cluster.name }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Cabinet number' %}:</td>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li>
|
||||
<a href="{% url 'assets:idc-detail' pk=idc.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
|
||||
<a href="{% url 'assets:cluster-detail' pk=cluster.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
|
||||
</li>
|
||||
<li class="active"><a href="{% url 'assets:idc-assets' pk=idc.id %}" class="text-center">
|
||||
<i class="fa fa-bar-chart-o"></i> {% trans 'IDC assets' %}</a>
|
||||
<li class="active"><a href="{% url 'assets:cluster-assets' pk=cluster.id %}" class="text-center">
|
||||
<i class="fa fa-bar-chart-o"></i> {% trans 'Cluster assets' %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -28,7 +28,7 @@
|
|||
<div class="col-sm-7" style="padding-left: 0;">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<span style="float: left">{% trans 'IDC assets' %} <b>{{ idc.name }} </b><span class="badge"></span></span>
|
||||
<span style="float: left">{% trans 'Cluster assets' %} <b>{{ cluster.name }} </b><span class="badge"></span></span>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
|
@ -45,7 +45,7 @@
|
|||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
<table class="table table-striped table-bordered table-hover " id="idc_assets_table" >
|
||||
<table class="table table-striped table-bordered table-hover " id="cluster_assets_table" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
|
@ -80,7 +80,7 @@
|
|||
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-info-circle"></i> {% trans 'Add assets to' %} {{ idc.name }}
|
||||
<i class="fa fa-info-circle"></i> {% trans 'Add assets to' %} {{ cluster.name }}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
|
@ -125,12 +125,12 @@ Array.prototype.remove = function(val) {
|
|||
}
|
||||
};
|
||||
|
||||
function updateIDCAssets(assets) {
|
||||
var the_url = "{% url 'api-assets:idc-update-assets' pk=idc.id %}";
|
||||
function updateClusterAssets(assets) {
|
||||
var the_url = "{% url 'api-assets:cluster-update-assets' pk=cluster.id %}";
|
||||
var body = {
|
||||
assets: Object.assign([], assets)
|
||||
};
|
||||
var $data_table = $("#idc_assets_table").DataTable();
|
||||
var $data_table = $("#cluster_assets_table").DataTable();
|
||||
var success = function(data) {
|
||||
$('.select2-selection__rendered').empty();
|
||||
$.map(jumpserver.assets_selected, function(asset_ip, index) {
|
||||
|
@ -147,12 +147,12 @@ function updateIDCAssets(assets) {
|
|||
});
|
||||
}
|
||||
|
||||
function deleteIDCAssets(assets) {
|
||||
var the_url = "{% url 'api-assets:idc-update-assets' pk=idc.id %}";
|
||||
function deleteClusterAssets(assets) {
|
||||
var the_url = "{% url 'api-assets:cluster-update-assets' pk=cluster.id %}";
|
||||
var body = {
|
||||
assets: Object.assign([], assets)
|
||||
};
|
||||
var $data_table = $("#idc_assets_table").DataTable();
|
||||
var $data_table = $("#cluster_assets_table").DataTable();
|
||||
var success = function(data) {
|
||||
$data_table.ajax.reload();
|
||||
};
|
||||
|
@ -175,7 +175,7 @@ $(document).ready(function () {
|
|||
delete jumpserver.assets_selected[data.id];
|
||||
});
|
||||
var options = {
|
||||
ele: $('#idc_assets_table'),
|
||||
ele: $('#cluster_assets_table'),
|
||||
buttons: [],
|
||||
order: [],
|
||||
columnDefs: [
|
||||
|
@ -190,7 +190,7 @@ $(document).ready(function () {
|
|||
$(td).html('<i class="fa fa-check text-navy"></i>')
|
||||
}
|
||||
}}],
|
||||
ajax_url: '{% url "api-assets:asset-list" %}?idc_id={{ idc.id }}',
|
||||
ajax_url: '{% url "api-assets:asset-list" %}?cluster_id={{ cluster.id }}',
|
||||
columns: [{data: function(){return ""}}, {data: "hostname" }, {data: "ip" }, {data: "port" },
|
||||
{data: "type" }, {data: "is_active" }],
|
||||
op_html: $('#actions').html()
|
||||
|
@ -204,11 +204,11 @@ $(document).ready(function () {
|
|||
return false;
|
||||
}
|
||||
var assets=[];
|
||||
var $data_table = $("#idc_assets_table").DataTable();
|
||||
var $data_table = $("#cluster_assets_table").DataTable();
|
||||
$.ajax({
|
||||
url: '{% url "api-assets:asset-list" %}',
|
||||
method: 'GET',
|
||||
data: {"idc_id": {{ idc.id }}},
|
||||
data: {"cluster_id": {{ cluster.id }}},
|
||||
dataType: 'json',
|
||||
success: function (result) {
|
||||
for(var i in result){
|
||||
|
@ -219,7 +219,7 @@ $(document).ready(function () {
|
|||
$.map(jumpserver.assets_selected, function(value, index) {
|
||||
assets.push(parseInt(index));
|
||||
});
|
||||
updateIDCAssets(assets);
|
||||
updateClusterAssets(assets);
|
||||
|
||||
}
|
||||
});
|
||||
|
@ -227,7 +227,7 @@ $(document).ready(function () {
|
|||
|
||||
.on('click', '#btn_bulk_update', function () {
|
||||
var action = $("#slct_bulk_update").val();
|
||||
var $data_table = $("#idc_assets_table").DataTable();
|
||||
var $data_table = $("#cluster_assets_table").DataTable();
|
||||
var id_list = [];
|
||||
var plain_id_list = [];
|
||||
var assets = [];
|
||||
|
@ -240,7 +240,7 @@ $(document).ready(function () {
|
|||
}
|
||||
$.ajax({
|
||||
url: '{% url "api-assets:asset-list" %}',
|
||||
data: {"idc_id": {{ idc.id }}},
|
||||
data: {"cluster_id": {{ cluster.id }}},
|
||||
dataType: 'json',
|
||||
method: 'GET',
|
||||
success: function (result) {
|
||||
|
@ -265,13 +265,13 @@ $(document).ready(function () {
|
|||
var success = function() {
|
||||
var msg = "{% trans 'Asset Deleted.' %}";
|
||||
swal("{% trans 'Asset Delete' %}", msg, "success");
|
||||
$('#idc_assets_table').DataTable().ajax.reload();
|
||||
$('#cluster_assets_table').DataTable().ajax.reload();
|
||||
};
|
||||
var fail = function() {
|
||||
var msg = "{% trans 'Asset Deleting failed.' %}";
|
||||
swal("{% trans 'Asset Delete' %}", msg, "error");
|
||||
};
|
||||
var url_delete = "{% url 'api-assets:idc-update-assets' pk=idc.id %}";
|
||||
var url_delete = "{% url 'api-assets:cluster-update-assets' pk=cluster.id %}";
|
||||
var body = {
|
||||
assets: Object.assign([], assets)
|
||||
};
|
|
@ -31,7 +31,7 @@
|
|||
<div class="panel-body">
|
||||
<div class="tab-content">
|
||||
<div id="tab-1" class="ibox float-e-margins tab-pane active"></div>
|
||||
<form id="IDCForm" method="post" class="form-horizontal">
|
||||
<form id="ClusterForm" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<h3 class="widget-head-color-box">基本信息</h3>
|
||||
{% bootstrap_field form.name layout="horizontal" %}
|
|
@ -14,18 +14,18 @@
|
|||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active">
|
||||
<a href="{% url 'assets:idc-detail' pk=idc.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
|
||||
<a href="{% url 'assets:cluster-detail' pk=cluster.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'assets:idc-assets' pk=idc.id %}" class="text-center">
|
||||
<i class="fa fa-bar-chart-o"></i> {% trans 'IDC assets' %}
|
||||
<a href="{% url 'assets:cluster-assets' pk=cluster.id %}" class="text-center">
|
||||
<i class="fa fa-bar-chart-o"></i> {% trans 'Cluster assets' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="pull-right">
|
||||
<a class="btn btn-outline btn-default" href="{% url 'assets:idc-update' pk=idc.id %}"><i class="fa fa-edit"></i>Update</a>
|
||||
<a class="btn btn-outline btn-default" href="{% url 'assets:cluster-update' pk=cluster.id %}"><i class="fa fa-edit"></i>Update</a>
|
||||
</li>
|
||||
<li class="pull-right">
|
||||
<a class="btn btn-outline btn-danger btn-delete-idc">
|
||||
<a class="btn btn-outline btn-danger btn-delete-cluster">
|
||||
<i class="fa fa-edit"></i>Delete
|
||||
</a>
|
||||
</li>
|
||||
|
@ -35,7 +35,7 @@
|
|||
<div class="col-sm-7" style="padding-left: 0;">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<span class="label"><b>{{ idc.name }}</b></span>
|
||||
<span class="label"><b>{{ cluster.name }}</b></span>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
|
@ -55,35 +55,35 @@
|
|||
<tbody>
|
||||
<tr class="no-borders-tr">
|
||||
<td width="20%">{% trans 'Name' %}:</td>
|
||||
<td><b>{{ idc.name }}</b></td>
|
||||
<td><b>{{ cluster.name }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Bandwidth' %}:</td>
|
||||
<td><b>{{ idc.bandwidth }}</b></td>
|
||||
<td><b>{{ cluster.bandwidth }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Contact' %}:</td>
|
||||
<td><b>{{ idc.contact }}</b></td>
|
||||
<td><b>{{ cluster.contact }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Phone' %}:</td>
|
||||
<td><b>{{ idc.phone }}</b></td>
|
||||
<td><b>{{ cluster.phone }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Address' %}:</td>
|
||||
<td><b>{{ idc.address }}</b></td>
|
||||
<td><b>{{ cluster.address }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Intranet' %}:</td>
|
||||
<td><b>{{ idc.Intranet }}</b></td>
|
||||
<td><b>{{ cluster.Intranet }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Extranet' %}:</td>
|
||||
<td><b>{{ idc.extranet }}</b></td>
|
||||
<td><b>{{ cluster.extranet }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Operator' %}:</td>
|
||||
<td><b>{{ idc.operator }}</b></td>
|
||||
<td><b>{{ cluster.operator }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Date created' %}:</td>
|
||||
|
@ -111,12 +111,12 @@
|
|||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
function idcDelete(name, url) {
|
||||
function clusterDelete(name, url) {
|
||||
function doDelete() {
|
||||
var body = {};
|
||||
var success = function() {
|
||||
swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success");
|
||||
window.location.href="{% url 'assets:idc-list' %}";
|
||||
window.location.href="{% url 'assets:cluster-list' %}";
|
||||
};
|
||||
var fail = function() {
|
||||
swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error");
|
||||
|
@ -146,11 +146,11 @@ function idcDelete(name, url) {
|
|||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
})
|
||||
.on('click', '.btn-delete-idc', function () {
|
||||
var name = $('.idc-details > tbody > tr').attr("data-name");
|
||||
var id = {{ idc.id }};
|
||||
var the_url = '{% url "api-assets:idc-detail" pk=99991937 %}'.replace(99991937, id);
|
||||
idcDelete(name, the_url);
|
||||
.on('click', '.btn-delete-cluster', function () {
|
||||
var name = $('.cluster-details > tbody > tr').attr("data-name");
|
||||
var id = {{ cluster.id }};
|
||||
var the_url = '{% url "api-assets:cluster-detail" pk=99991937 %}'.replace(99991937, id);
|
||||
clusterDelete(name, the_url);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -7,7 +7,7 @@
|
|||
{% block table_search %}{% endblock %}
|
||||
{% block table_container %}
|
||||
<div class="uc pull-left m-l-5 m-r-5">
|
||||
<a href="{% url "assets:idc-create" %}" class="btn btn-sm btn-primary"> {% trans "Create IDC" %} </a>
|
||||
<a href="{% url "assets:idc-create" %}" class="btn btn-sm btn-primary"> {% trans "Create Cluster" %} </a>
|
||||
</div>
|
||||
<table class="table table-striped table-bordered table-hover " id="idc_list_table" >
|
||||
<thead>
|
||||
|
@ -100,13 +100,13 @@ $(document).ready(function(){
|
|||
closeOnConfirm: false
|
||||
}, function() {
|
||||
var success = function() {
|
||||
var msg = "{% trans 'IDC Deleted.' %}";
|
||||
swal("{% trans 'IDC Delete' %}", msg, "success");
|
||||
var msg = "{% trans 'Cluster Deleted.' %}";
|
||||
swal("{% trans 'Cluster Delete' %}", msg, "success");
|
||||
$('#idc_list_table').DataTable().ajax.reload();
|
||||
};
|
||||
var fail = function() {
|
||||
var msg = "{% trans 'IDC Deleting failed.' %}";
|
||||
swal("{% trans 'IDC Delete' %}", msg, "error");
|
||||
var msg = "{% trans 'Cluster Deleting failed.' %}";
|
||||
swal("{% trans 'Cluster Delete' %}", msg, "error");
|
||||
};
|
||||
var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list);
|
||||
APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail});
|
|
@ -69,7 +69,7 @@ $(document).ready(function(){
|
|||
|
||||
.on('click', '.btn_admin_user_delete', function () {
|
||||
var $this = $(this);
|
||||
var $data_table = $('#idc_list_table').DataTable();
|
||||
var $data_table = $('#cluster_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:system-user-detail" pk=99991937 %}'.replace('99991937', uid);
|
||||
|
|
|
@ -10,7 +10,7 @@ app_name = 'assets'
|
|||
router = BulkRouter()
|
||||
router.register(r'v1/groups', api.AssetGroupViewSet, 'asset-group')
|
||||
router.register(r'v1/assets', api.AssetViewSet, 'asset')
|
||||
router.register(r'v1/idc', api.IDCViewSet, 'idc')
|
||||
router.register(r'v1/clusters', api.ClusterViewSet, 'cluster')
|
||||
router.register(r'v1/admin-user', api.AdminUserViewSet, 'admin-user')
|
||||
router.register(r'v1/system-user', api.SystemUserViewSet, 'system-user')
|
||||
|
||||
|
@ -47,9 +47,9 @@ urlpatterns = [
|
|||
url(r'^v1/groups/(?P<pk>[0-9a-zA-Z\-]+)/system-users/$',
|
||||
api.AssetGroupUpdateSystemUserApi.as_view(), name='asset-groups-update-systemusers'),
|
||||
|
||||
# update the IDC, and add or delete the assets to the IDC
|
||||
url(r'^v1/idc/(?P<pk>[0-9a-zA-Z\-]+)/assets/$',
|
||||
api.IDCUpdateAssetsApi.as_view(), name='idc-update-assets'),
|
||||
# update the Cluster, and add or delete the assets to the Cluster
|
||||
url(r'^v1/cluster/(?P<pk>[0-9a-zA-Z\-]+)/assets/$',
|
||||
api.ClusterUpdateAssetsApi.as_view(), name='cluster-update-assets'),
|
||||
|
||||
]
|
||||
|
||||
|
|
|
@ -27,13 +27,13 @@ urlpatterns = [
|
|||
url(r'^asset-group/(?P<pk>[0-9a-zA-Z\-]+)/update/$', views.AssetGroupUpdateView.as_view(), name='asset-group-update'),
|
||||
url(r'^asset-group/(?P<pk>[0-9a-zA-Z\-]+)/delete/$', views.AssetGroupDeleteView.as_view(), name='asset-group-delete'),
|
||||
|
||||
# Resource idc url
|
||||
url(r'^idc/$', views.IDCListView.as_view(), name='idc-list'),
|
||||
url(r'^idc/create/$', views.IDCCreateView.as_view(), name='idc-create'),
|
||||
url(r'^idc/(?P<pk>[0-9a-zA-Z\-]+)/$', views.IDCDetailView.as_view(), name='idc-detail'),
|
||||
url(r'^idc/(?P<pk>[0-9a-zA-Z\-]+)/update/', views.IDCUpdateView.as_view(), name='idc-update'),
|
||||
url(r'^idc/(?P<pk>[0-9a-zA-Z\-]+)/delete/$', views.IDCDeleteView.as_view(), name='idc-delete'),
|
||||
url(r'^idc/(?P<pk>[0-9a-zA-Z\-]+)/assets/$', views.IDCAssetsView.as_view(), name='idc-assets'),
|
||||
# Resource cluster url
|
||||
url(r'^cluster/$', views.ClusterListView.as_view(), name='cluster-list'),
|
||||
url(r'^cluster/create/$', views.ClusterCreateView.as_view(), name='cluster-create'),
|
||||
url(r'^cluster/(?P<pk>[0-9a-zA-Z\-]+)/$', views.ClusterDetailView.as_view(), name='cluster-detail'),
|
||||
url(r'^cluster/(?P<pk>[0-9a-zA-Z\-]+)/update/', views.ClusterUpdateView.as_view(), name='cluster-update'),
|
||||
url(r'^cluster/(?P<pk>[0-9a-zA-Z\-]+)/delete/$', views.ClusterDeleteView.as_view(), name='cluster-delete'),
|
||||
url(r'^cluster/(?P<pk>[0-9a-zA-Z\-]+)/assets/$', views.ClusterAssetsView.as_view(), name='cluster-assets'),
|
||||
|
||||
# Resource admin user url
|
||||
url(r'^admin-user/$', views.AdminUserListView.as_view(), name='admin-user-list'),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# coding:utf-8
|
||||
from .asset import *
|
||||
from .group import *
|
||||
from .idc import *
|
||||
from .cluster import *
|
||||
from .system_user import *
|
||||
from .admin_user import *
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ from django.contrib.messages.views import SuccessMessageMixin
|
|||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||
|
||||
from .. import forms
|
||||
from ..models import Asset, AssetGroup, AdminUser, IDC, SystemUser
|
||||
from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser
|
||||
from ..hands import AdminUserRequiredMixin
|
||||
|
||||
__all__ = ['AdminUserCreateView', 'AdminUserDetailView',
|
||||
|
|
|
@ -25,7 +25,7 @@ from django.shortcuts import get_object_or_404, redirect, reverse
|
|||
from common.mixins import JSONResponseMixin
|
||||
from common.utils import get_object_or_none
|
||||
from .. import forms
|
||||
from ..models import Asset, AssetGroup, AdminUser, IDC, SystemUser
|
||||
from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser
|
||||
from ..hands import AdminUserRequiredMixin
|
||||
from ..tasks import update_assets_hardware_info
|
||||
|
||||
|
@ -283,7 +283,7 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
|
|||
asset = get_object_or_none(Asset, id=id_)
|
||||
for k, v in asset_dict.items():
|
||||
if k == 'idc':
|
||||
v = get_object_or_none(IDC, name=v)
|
||||
v = get_object_or_none(Cluster, name=v)
|
||||
elif k == 'is_active':
|
||||
v = bool(v)
|
||||
elif k == 'admin_user':
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
# coding:utf-8
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import TemplateView, ListView, View
|
||||
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||
from .. import forms
|
||||
from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser
|
||||
from ..hands import AdminUserRequiredMixin
|
||||
|
||||
|
||||
__all__ = ['ClusterListView', 'ClusterCreateView', 'ClusterUpdateView',
|
||||
'ClusterDetailView', 'ClusterDeleteView', 'ClusterAssetsView']
|
||||
|
||||
|
||||
class ClusterListView(AdminUserRequiredMixin, TemplateView):
|
||||
template_name = 'assets/cluster_list.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Assets'),
|
||||
'action': _('Cluster list'),
|
||||
# 'keyword': self.request.GET.get('keyword', '')
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ClusterListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class ClusterCreateView(AdminUserRequiredMixin, CreateView):
|
||||
model = Cluster
|
||||
form_class = forms.ClusterForm
|
||||
template_name = 'assets/cluster_create_update.html'
|
||||
success_url = reverse_lazy('assets:cluster-list')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('assets'),
|
||||
'action': _('Create Cluster'),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ClusterCreateView, self).get_context_data(**kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
cluster = form.save(commit=False)
|
||||
cluster.created_by = self.request.user.username or 'System'
|
||||
cluster.save()
|
||||
return super(ClusterCreateView, self).form_valid(form)
|
||||
|
||||
|
||||
class ClusterUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||
model = Cluster
|
||||
form_class = forms.ClusterForm
|
||||
template_name = 'assets/cluster_create_update.html'
|
||||
context_object_name = 'cluster'
|
||||
success_url = reverse_lazy('assets:cluster-list')
|
||||
|
||||
def form_valid(self, form):
|
||||
cluster = form.save(commit=False)
|
||||
cluster.save()
|
||||
return super(ClusterUpdateView, self).form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('assets'),
|
||||
'action': _('Update Cluster'),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ClusterUpdateView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class ClusterDetailView(AdminUserRequiredMixin, DetailView):
|
||||
model = Cluster
|
||||
template_name = 'assets/cluster_detail.html'
|
||||
context_object_name = 'cluster'
|
||||
|
||||
|
||||
class ClusterAssetsView(AdminUserRequiredMixin, DetailView):
|
||||
model = Cluster
|
||||
template_name = 'assets/cluster_assets.html'
|
||||
context_object_name = 'cluster'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
assets_remain = Asset.objects.exclude(id__in=self.object.assets.all())
|
||||
|
||||
context = {
|
||||
'app': _('Assets'),
|
||||
'action': _('Asset detail'),
|
||||
'groups': AssetGroup.objects.all(),
|
||||
'system_users': SystemUser.objects.all(),
|
||||
'assets_remain': assets_remain,
|
||||
'assets': [asset for asset in Asset.objects.all() if asset not in assets_remain],
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ClusterAssetsView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class ClusterDeleteView(AdminUserRequiredMixin, DeleteView):
|
||||
model = Cluster
|
||||
template_name = 'assets/delete_confirm.html'
|
||||
success_url = reverse_lazy('assets:cluster-list')
|
|
@ -9,7 +9,7 @@ from django.views.generic.detail import DetailView, SingleObjectMixin
|
|||
from django.shortcuts import get_object_or_404, reverse, redirect
|
||||
|
||||
from .. import forms
|
||||
from ..models import Asset, AssetGroup, AdminUser, IDC, SystemUser
|
||||
from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser
|
||||
from ..hands import AdminUserRequiredMixin
|
||||
|
||||
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
# coding:utf-8
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import TemplateView, ListView, View
|
||||
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||
from .. import forms
|
||||
from ..models import Asset, AssetGroup, AdminUser, IDC, SystemUser
|
||||
from ..hands import AdminUserRequiredMixin
|
||||
|
||||
|
||||
__all__ = ['IDCListView', 'IDCCreateView', 'IDCUpdateView',
|
||||
'IDCDetailView', 'IDCDeleteView', 'IDCAssetsView']
|
||||
|
||||
|
||||
class IDCListView(AdminUserRequiredMixin, TemplateView):
|
||||
template_name = 'assets/idc_list.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Assets'),
|
||||
'action': _('IDC list'),
|
||||
# 'keyword': self.request.GET.get('keyword', '')
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(IDCListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class IDCCreateView(AdminUserRequiredMixin, CreateView):
|
||||
model = IDC
|
||||
form_class = forms.IDCForm
|
||||
template_name = 'assets/idc_create_update.html'
|
||||
success_url = reverse_lazy('assets:idc-list')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('assets'),
|
||||
'action': _('Create IDC'),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(IDCCreateView, self).get_context_data(**kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
idc = form.save(commit=False)
|
||||
idc.created_by = self.request.user.username or 'System'
|
||||
idc.save()
|
||||
return super(IDCCreateView, self).form_valid(form)
|
||||
|
||||
|
||||
class IDCUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||
model = IDC
|
||||
form_class = forms.IDCForm
|
||||
template_name = 'assets/idc_create_update.html'
|
||||
context_object_name = 'idc'
|
||||
success_url = reverse_lazy('assets:idc-list')
|
||||
|
||||
def form_valid(self, form):
|
||||
idc = form.save(commit=False)
|
||||
idc.save()
|
||||
return super(IDCUpdateView, self).form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('assets'),
|
||||
'action': _('Update IDC'),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(IDCUpdateView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class IDCDetailView(AdminUserRequiredMixin, DetailView):
|
||||
model = IDC
|
||||
template_name = 'assets/idc_detail.html'
|
||||
context_object_name = 'idc'
|
||||
|
||||
|
||||
class IDCAssetsView(AdminUserRequiredMixin, DetailView):
|
||||
model = IDC
|
||||
template_name = 'assets/idc_assets.html'
|
||||
context_object_name = 'idc'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
assets_remain = Asset.objects.exclude(id__in=self.object.assets.all())
|
||||
|
||||
context = {
|
||||
'app': _('Assets'),
|
||||
'action': _('Asset detail'),
|
||||
'groups': AssetGroup.objects.all(),
|
||||
'system_users': SystemUser.objects.all(),
|
||||
'assets_remain': assets_remain,
|
||||
'assets': [asset for asset in Asset.objects.all() if asset not in assets_remain],
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(IDCAssetsView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class IDCDeleteView(AdminUserRequiredMixin, DeleteView):
|
||||
model = IDC
|
||||
template_name = 'assets/delete_confirm.html'
|
||||
success_url = reverse_lazy('assets:idc-list')
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
[{"model": "users.usergroup", "pk": "0460a32e-59c9-42cc-81a5-7e0a13fc0085", "fields": {"is_discard": false, "discard_time": null, "name": "Default", "comment": "Default user group", "date_created": "2017-11-23T03:59:09.875Z", "created_by": "System"}}, {"model": "assets.idc", "pk": "937922e3-e2b7-42aa-b460-6b276901f53a", "fields": {"name": "Default", "bandwidth": "", "contact": "", "phone": "", "address": "", "intranet": "", "extranet": "", "date_created": "2017-11-23T03:59:09.882Z", "operator": "", "created_by": "System", "comment": "Default IDC"}}, {"model": "assets.assetgroup", "pk": "f758dc94-b979-4edf-9afc-f9171f9d2d6a", "fields": {"name": "Default", "created_by": "", "date_created": "2017-11-23T03:59:09.883Z", "comment": "Default asset group", "system_users": []}}, {"model": "users.user", "pk": "bb318c48-4f50-483e-a165-89d7f18e9e95", "fields": {"password": "pbkdf2_sha256$36000$kHqN5uCVaAk9$SXWzKLwBg68/2W8NLSNJIaVBJc60F26p8RO9E3oSskI=", "last_login": null, "first_name": "", "last_name": "", "is_active": true, "date_joined": "2017-11-23T03:59:09.828Z", "username": "admin", "name": "Administrator", "email": "admin@jumpserver.org", "role": "Admin", "avatar": "", "wechat": "", "phone": null, "enable_otp": false, "secret_key_otp": "", "_private_key": "", "_public_key": "", "comment": "Administrator is the super user of system", "is_first_login": false, "date_expired": "2087-11-06T03:59:09.829Z", "created_by": "System", "user_permissions": [], "groups": ["0460a32e-59c9-42cc-81a5-7e0a13fc0085"]}}]
|
||||
[{"model": "users.usergroup", "pk": "2e0b2a25-b32f-44a0-b087-f0f17de66e26", "fields": {"is_discard": false, "discard_time": null, "name": "Default", "comment": "Default user group", "date_created": "2017-12-07T08:20:09.593Z", "created_by": "System"}}, {"model": "assets.cluster", "pk": "c0df1aa0-bde7-4226-a69a-d02976888456", "fields": {"name": "Default", "bandwidth": "", "contact": "", "phone": "", "address": "", "intranet": "", "extranet": "", "date_created": "2017-12-07T08:20:09.606Z", "operator": "", "created_by": "System", "comment": "Default Cluster"}}, {"model": "assets.assetgroup", "pk": "881a0460-7989-42af-a588-957efe57fb8e", "fields": {"name": "Default", "created_by": "", "date_created": "2017-12-07T08:20:09.610Z", "comment": "Default asset group", "system_users": []}}, {"model": "users.user", "pk": "edc529d5-0377-4456-831f-ec42cf5b34d2", "fields": {"password": "pbkdf2_sha256$36000$3VcSL8Ap6zHd$14Y4+uZHRU8gwFgEXdIEZZ2+NWV15sRBV2YWgWbdyhY=", "last_login": null, "first_name": "", "last_name": "", "is_active": true, "date_joined": "2017-12-07T08:20:09.494Z", "username": "admin", "name": "Administrator", "email": "admin@jumpserver.org", "role": "Admin", "avatar": "", "wechat": "", "phone": null, "enable_otp": false, "secret_key_otp": "", "_private_key": "", "_public_key": "", "comment": "Administrator is the super user of system", "is_first_login": false, "date_expired": "2087-11-20T08:20:09.494Z", "created_by": "System", "user_permissions": [], "groups": ["2e0b2a25-b32f-44a0-b087-f0f17de66e26"]}}]
|
|
@ -467,7 +467,7 @@ msgstr "系统用户"
|
|||
|
||||
#: assets/models/asset.py:52 assets/templates/assets/asset_detail.html:85
|
||||
#: templates/_nav.html:23
|
||||
msgid "IDC"
|
||||
msgid "Cluster"
|
||||
msgstr "机房"
|
||||
|
||||
#: assets/models/asset.py:53 assets/templates/assets/asset_detail.html:129
|
||||
|
@ -618,8 +618,8 @@ msgid "System"
|
|||
msgstr "系统"
|
||||
|
||||
#: assets/models/idc.py:43
|
||||
msgid "Default IDC"
|
||||
msgstr "默认IDC"
|
||||
msgid "Default Cluster"
|
||||
msgstr "默认Cluster"
|
||||
|
||||
#: assets/models/user.py:24
|
||||
#, python-format
|
||||
|
@ -1080,8 +1080,8 @@ msgstr "您确定删除吗?"
|
|||
#: assets/templates/assets/idc_assets.html:23
|
||||
#: assets/templates/assets/idc_assets.html:31
|
||||
#: assets/templates/assets/idc_detail.html:21
|
||||
msgid "IDC assets"
|
||||
msgstr "IDC资产"
|
||||
msgid "Cluster assets"
|
||||
msgstr "Cluster资产"
|
||||
|
||||
#: assets/templates/assets/idc_assets.html:68
|
||||
#, fuzzy
|
||||
|
@ -1104,25 +1104,25 @@ msgid "Asset Updated"
|
|||
msgstr "更新"
|
||||
|
||||
#: assets/templates/assets/idc_list.html:10 assets/views/idc.py:39
|
||||
msgid "Create IDC"
|
||||
msgstr "创建IDC"
|
||||
msgid "Create Cluster"
|
||||
msgstr "创建Cluster"
|
||||
|
||||
#: assets/templates/assets/idc_list.html:95
|
||||
msgid "This will delete the selected idc"
|
||||
msgstr "删除选择IDC"
|
||||
msgstr "删除选择Cluster"
|
||||
|
||||
#: assets/templates/assets/idc_list.html:103
|
||||
msgid "IDC Deleted."
|
||||
msgid "Cluster Deleted."
|
||||
msgstr "已被删除"
|
||||
|
||||
#: assets/templates/assets/idc_list.html:104
|
||||
#: assets/templates/assets/idc_list.html:109
|
||||
msgid "IDC Delete"
|
||||
msgid "Cluster Delete"
|
||||
msgstr "删除"
|
||||
|
||||
#: assets/templates/assets/idc_list.html:108
|
||||
msgid "IDC Deleting failed."
|
||||
msgstr "IDC删除失败"
|
||||
msgid "Cluster Deleting failed."
|
||||
msgstr "Cluster删除失败"
|
||||
|
||||
#: assets/templates/assets/system_user_asset.html:20
|
||||
#: assets/templates/assets/system_user_detail.html:22
|
||||
|
@ -1208,8 +1208,8 @@ msgid "Asset group detail"
|
|||
msgstr "资产组详情"
|
||||
|
||||
#: assets/views/idc.py:23
|
||||
msgid "IDC list"
|
||||
msgstr "IDC列表"
|
||||
msgid "Cluster list"
|
||||
msgstr "Cluster列表"
|
||||
|
||||
#: assets/views/idc.py:38 assets/views/idc.py:65
|
||||
#: ops/templates/ops/task_detail.html:84
|
||||
|
@ -1217,8 +1217,8 @@ msgid "assets"
|
|||
msgstr "资产管理"
|
||||
|
||||
#: assets/views/idc.py:66
|
||||
msgid "Update IDC"
|
||||
msgstr "更新IDC"
|
||||
msgid "Update Cluster"
|
||||
msgstr "更新Cluster"
|
||||
|
||||
#: assets/views/system_user.py:31
|
||||
msgid "System user list"
|
||||
|
|
|
@ -29,7 +29,7 @@ Options = namedtuple('Options', [
|
|||
'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args',
|
||||
'scp_extra_args', 'become', 'become_method', 'become_user',
|
||||
'verbosity', 'check', 'extra_vars', 'playbook_path', 'passwords',
|
||||
'diff',
|
||||
'diff', 'gathering'
|
||||
])
|
||||
|
||||
|
||||
|
@ -58,6 +58,7 @@ def get_default_options():
|
|||
playbook_path='/etc/ansible/',
|
||||
passwords=None,
|
||||
diff=False,
|
||||
gathering='implicit',
|
||||
)
|
||||
return options
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@ import uuid
|
|||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common.utils import signer
|
||||
|
||||
__all__ = ["AdHoc", "History"]
|
||||
__all__ = ["AdHoc", "AdHocRunHistory"]
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -16,6 +17,8 @@ logger = logging.getLogger(__name__)
|
|||
class AdHoc(models.Model):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, blank=True, verbose_name=_('Name'))
|
||||
is_deleted = models.BooleanField(default=False)
|
||||
date_create = models.DateTimeField(auto_created=True)
|
||||
|
||||
@property
|
||||
def short_id(self):
|
||||
|
@ -39,7 +42,7 @@ class AdHocData(models.Model):
|
|||
become = models.BooleanField(default=False, verbose_name=_("Become"))
|
||||
become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4)
|
||||
become_user = models.CharField(default='root', max_length=64)
|
||||
become_pass = models.CharField(default='', max_length=128)
|
||||
_become_pass = models.CharField(default='', max_length=128)
|
||||
pattern = models.CharField(max_length=64, default='', verbose_name=_('Pattern'))
|
||||
created_by = models.CharField(max_length=64, verbose_name=_('Create by'))
|
||||
date_created = models.DateTimeField(auto_created=True)
|
||||
|
@ -60,15 +63,29 @@ class AdHocData(models.Model):
|
|||
def hosts(self, item):
|
||||
self._hosts = json.dumps(item)
|
||||
|
||||
@property
|
||||
def become_pass(self):
|
||||
return signer.unsign(self._become_pass)
|
||||
|
||||
@become_pass.setter
|
||||
def become_pass(self, password):
|
||||
self._become_pass = signer.sign(password)
|
||||
|
||||
@property
|
||||
def short_version(self):
|
||||
return str(self.version).split('-')[-1]
|
||||
|
||||
def run(self):
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
return "{} of {}".format(self.subject.name, self.short_version)
|
||||
|
||||
class Meta:
|
||||
db_table = "ops_adhoc_data"
|
||||
|
||||
class AdHocHistory(models.Model):
|
||||
|
||||
class AdHocRunHistory(models.Model):
|
||||
uuid = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
adhoc = models.ForeignKey(AdHocData, on_delete=models.CASCADE)
|
||||
date_start = models.DateTimeField(auto_now_add=True, verbose_name=_('Start time'))
|
||||
|
@ -85,3 +102,6 @@ class AdHocHistory(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return self.short_id
|
||||
|
||||
class Meta:
|
||||
db_table = "ops_adhoc_history"
|
||||
|
|
|
@ -9,79 +9,18 @@ import uuid
|
|||
|
||||
from django.utils import timezone
|
||||
|
||||
from assets.models import Asset
|
||||
from common.utils import get_logger
|
||||
from .ansible.runner import AdHocRunner
|
||||
from common.utils import get_logger, get_object_or_none
|
||||
from .ansible import AdHocRunner
|
||||
from assets.utils import get_assets_by_hostname_list
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
def run_AdHoc(task_tuple, assets,
|
||||
task_name='Ansible AdHoc runner',
|
||||
task_id=None, pattern='all',
|
||||
record=True, verbose=True):
|
||||
"""
|
||||
:param task_tuple: (('module_name', 'module_args'), ('module_name', 'module_args'))
|
||||
:param assets: [asset1, asset2]
|
||||
:param task_name:
|
||||
:param task_id:
|
||||
:param pattern:
|
||||
:param record:
|
||||
:param verbose:
|
||||
:return: summary: {'success': [], 'failed': [{'192.168.1.1': 'msg'}]}
|
||||
result: {'contacted': {'hostname': [{''}, {''}], 'dark': []}
|
||||
"""
|
||||
|
||||
if not assets:
|
||||
logger.warning('Empty assets, runner cancel')
|
||||
return
|
||||
if isinstance(assets[0], Asset):
|
||||
assets = [asset._to_secret_json() for asset in assets]
|
||||
if task_id is None:
|
||||
task_id = str(uuid.uuid4())
|
||||
|
||||
runner = AdHocRunner(assets)
|
||||
if record:
|
||||
from .models import Playbook
|
||||
if not Playbook.objects.filter(uuid=task_id):
|
||||
record = Playbook(uuid=task_id,
|
||||
name=task_name,
|
||||
assets=','.join(str(asset['id']) for asset in assets),
|
||||
module_args=task_tuple,
|
||||
pattern=pattern)
|
||||
record.save()
|
||||
else:
|
||||
record = Playbook.objects.get(uuid=task_id)
|
||||
record.date_start = timezone.now()
|
||||
record.date_finished = None
|
||||
record.timedelta = None
|
||||
record.is_finished = False
|
||||
record.is_success = False
|
||||
record.save()
|
||||
ts_start = time.time()
|
||||
if verbose:
|
||||
logger.debug('Start runner {}'.format(task_name))
|
||||
result = runner.run(task_tuple, pattern=pattern, task_name=task_name)
|
||||
timedelta = round(time.time() - ts_start, 2)
|
||||
summary = runner.clean_result()
|
||||
if record:
|
||||
record.date_finished = timezone.now()
|
||||
record.is_finished = True
|
||||
if verbose:
|
||||
record.result = json.dumps(result, indent=4, sort_keys=True)
|
||||
record.summary = json.dumps(summary)
|
||||
record.timedelta = timedelta
|
||||
if len(summary['failed']) == 0:
|
||||
record.is_success = True
|
||||
else:
|
||||
record.is_success = False
|
||||
record.save()
|
||||
return summary, result
|
||||
|
||||
|
||||
UUID_PATTERN = re.compile(r'[0-9a-zA-Z\-]{36}')
|
||||
|
||||
|
||||
def run_AdHoc():
|
||||
pass
|
||||
|
||||
|
||||
def is_uuid(s):
|
||||
if UUID_PATTERN.match(s):
|
||||
return True
|
||||
|
@ -99,3 +38,60 @@ def asset_to_dict_with_credential(asset):
|
|||
|
||||
def system_user_to_dict_with_credential(system_user):
|
||||
return system_user._to_secret_json()
|
||||
|
||||
|
||||
def get_hosts_with_admin(hostname_list):
|
||||
assets = get_assets_by_hostname_list(hostname_list)
|
||||
return [asset._to_secret_json for asset in assets]
|
||||
|
||||
|
||||
def get_hosts(hostname_list):
|
||||
assets = get_assets_by_hostname_list(hostname_list)
|
||||
return [asset.to_json for asset in assets]
|
||||
|
||||
|
||||
def get_run_user(name):
|
||||
from assets.models import SystemUser
|
||||
system_user = get_object_or_none(SystemUser, name=name)
|
||||
if system_user is None:
|
||||
return {}
|
||||
else:
|
||||
return system_user._to_secret_json()
|
||||
|
||||
|
||||
def get_hosts_with_run_user(hostname_list, run_as):
|
||||
hosts_dict = get_hosts(hostname_list)
|
||||
system_user_dct = get_run_user(run_as)
|
||||
|
||||
for host in hosts_dict:
|
||||
host.update(system_user_dct)
|
||||
return hosts_dict
|
||||
|
||||
|
||||
def hosts_add_become(hosts, adhoc_data):
|
||||
if adhoc_data.become:
|
||||
become_data = {
|
||||
"become": {
|
||||
"method": adhoc_data.become_method,
|
||||
"user": adhoc_data.become_user,
|
||||
"pass": adhoc_data.become_pass,
|
||||
}
|
||||
}
|
||||
for host in hosts:
|
||||
host.update(become_data)
|
||||
return hosts
|
||||
|
||||
|
||||
def run_adhoc(adhoc_data, forks=10):
|
||||
tasks = adhoc_data.tasks
|
||||
hostname_list = adhoc_data.hosts
|
||||
adhoc_name = adhoc_data.subject.name
|
||||
|
||||
if adhoc_data.run_as_admin:
|
||||
hosts = get_hosts_with_admin(adhoc_data.hosts)
|
||||
else:
|
||||
hosts = get_hosts_with_run_user(hostname_list, adhoc_data.run_as)
|
||||
hosts_add_become(hosts, adhoc_data) # admin user 自带become
|
||||
|
||||
runner = AdHocRunner(hosts)
|
||||
runner.set_option('forks', forks)
|
||||
|
|
|
@ -9,7 +9,7 @@ from django.views.generic import ListView, DetailView, View
|
|||
from django.utils import timezone
|
||||
from django.shortcuts import redirect, reverse
|
||||
|
||||
from .models import AdHoc, AdHocData, AdHocHistory
|
||||
from .models import AdHoc, AdHocData, AdHocRunHistory
|
||||
from ops.tasks import rerun_task
|
||||
|
||||
|
||||
|
@ -63,7 +63,7 @@ class TaskListView(ListView):
|
|||
|
||||
|
||||
class TaskDetailView(DetailView):
|
||||
model = AdHocHistory
|
||||
model = AdHocRunHistory
|
||||
template_name = 'ops/task_detail.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<ul class="nav nav-second-level">
|
||||
<li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset' %}</a></li>
|
||||
<li id="asset-group"><a href="{% url 'assets:asset-group-list' %}">{% trans 'Asset group' %}</a></li>
|
||||
<li id="idc"><a href="{% url 'assets:idc-list' %}">{% trans 'IDC' %}</a></li>
|
||||
<li id="cluster"><a href="{% url 'assets:cluster-list' %}">{% trans 'Cluster' %}</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>
|
||||
</ul>
|
||||
|
|
|
@ -9,8 +9,8 @@ generate_fake()
|
|||
EOF
|
||||
|
||||
python ../apps/manage.py dbshell << EOF
|
||||
delete from django_content_type;
|
||||
delete from auth_permission;
|
||||
delete from django_content_type;
|
||||
EOF
|
||||
|
||||
|
||||
|
|
|
@ -8,14 +8,11 @@ init_model()
|
|||
from assets.models import *
|
||||
init_model()
|
||||
|
||||
from audits.models import LoginLog
|
||||
LoginLog.objects.all().delete()
|
||||
EOF
|
||||
|
||||
|
||||
python ../apps/manage.py dbshell << EOF
|
||||
delete from django_content_type;
|
||||
delete from auth_permission;
|
||||
delete from django_content_type;
|
||||
EOF
|
||||
|
||||
python ../apps/manage.py dumpdata > ../apps/fixtures/init.json
|
||||
|
|
Loading…
Reference in New Issue