[Change] 修改idc => cluster

pull/828/merge
ibuler 7 years ago
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,
'groups': [group.name for group in self.groups.all()],
}
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()],
}
"""
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,77 +9,16 @@ 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__)
UUID_PATTERN = re.compile(r'[0-9a-zA-Z\-]{36}')
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):
@ -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…
Cancel
Save