Commit 3aea9941 authored by ibuler's avatar ibuler

asset import

parent c1c9c7b6
...@@ -309,4 +309,8 @@ class AssetTagForm(forms.ModelForm): ...@@ -309,4 +309,8 @@ class AssetTagForm(forms.ModelForm):
} }
help_texts = { help_texts = {
'name': '* required', 'name': '* required',
} }
\ No newline at end of file
class FileForm(forms.Form):
file = forms.FileField()
\ No newline at end of file
...@@ -309,12 +309,12 @@ class Asset(models.Model): ...@@ -309,12 +309,12 @@ class Asset(models.Model):
cabinet_no = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Cabinet number')) cabinet_no = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Cabinet number'))
cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position')) cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position'))
number = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Asset number')) number = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Asset number'))
status = models.CharField(choices=STATUS_CHOICES, max_length=1, null=True, blank=True, status = models.CharField(choices=STATUS_CHOICES, max_length=8, null=True, blank=True,
default='I', verbose_name=_('Asset status')) default='In use', verbose_name=_('Asset status'))
type = models.CharField(choices=TYPE_CHOICES, max_length=16, blank=True, null=True, type = models.CharField(choices=TYPE_CHOICES, max_length=16, blank=True, null=True,
default='Server', verbose_name=_('Asset type'),) default='Server', verbose_name=_('Asset type'),)
env = models.CharField(choices=ENV_CHOICES, max_length=8, blank=True, null=True, env = models.CharField(choices=ENV_CHOICES, max_length=8, blank=True, null=True,
default='P', verbose_name=_('Asset environment'),) default='Prod', verbose_name=_('Asset environment'),)
sn = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Serial number')) sn = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Serial number'))
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
is_active = models.BooleanField(default=True, verbose_name=_('Is active')) is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
......
...@@ -43,7 +43,6 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): ...@@ -43,7 +43,6 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
# system_users = SystemUserSerializer(many=True, read_only=True) # system_users = SystemUserSerializer(many=True, read_only=True)
# admin_user = AdminUserSerializer(many=False, read_only=True) # admin_user = AdminUserSerializer(many=False, read_only=True)
hardware = serializers.SerializerMethodField() hardware = serializers.SerializerMethodField()
type_display = serializers.SerializerMethodField()
class Meta(object): class Meta(object):
model = Asset model = Asset
...@@ -51,15 +50,16 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): ...@@ -51,15 +50,16 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
@staticmethod @staticmethod
def get_hardware(obj): def get_hardware(obj):
return '%s %s %s' % (obj.cpu, obj.memory, obj.disk) if obj.cpu:
return '%s %s %s' % (obj.cpu, obj.memory, obj.disk)
@staticmethod
def get_type_display(obj):
if obj.type:
return obj.type.value
else: else:
return '' return ''
def get_field_names(self, declared_fields, info):
fields = super(AssetSerializer, self).get_field_names(declared_fields, info)
fields.extend(['get_type_display', 'get_env_display'])
return fields
class AssetGrantedSerializer(serializers.ModelSerializer): class AssetGrantedSerializer(serializers.ModelSerializer):
system_users = SystemUserSerializer(many=True, read_only=True) system_users = SystemUserSerializer(many=True, read_only=True)
......
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_id %}asset_import_modal{% endblock %}
{% block modal_title%}{% trans "Import asset" %}{% endblock %}
{% block modal_body %}
<p class="text-success">{% trans "Download template or use export excel format" %}</p>
<form method="post" action="{% url 'assets:asset-import' %}" id="fm_asset_import" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label class="control-label" for="id_assets">{% trans "Template" %}</label>
<a href="{{ MEDIA_URL }}files/asset_import_template.xlsx" style="display: block">{% trans 'Download' %}</a>
</div>
<div class="form-group">
<label class="control-label" for="id_users">{% trans "Asset excel file" %}</label>
<input id="id_assets" type="file" name="file" />
</div>
</form>
<p>
<p class="text-success" id="id_created"></p>
<p id="id_created_detail"></p>
<p class="text-warning" id="id_updated"></p>
<p id="id_updated_detail"></p>
<p class="text-danger" id="id_failed"></p>
<p id="id_failed_detail"></p>
</p>
{% endblock %}
{% block modal_confirm_id %}btn_asset_import{% endblock %}
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
</tr> </tr>
<tr> <tr>
<td>{% trans 'Asset status' %}:</td> <td>{% trans 'Asset status' %}:</td>
<td><b>{{ asset.status }}</b></td> <td><b>{{ asset.get_status_display() }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Is active' %}:</td> <td>{% trans 'Is active' %}:</td>
......
...@@ -48,7 +48,6 @@ ...@@ -48,7 +48,6 @@
{% block table_container %} {% block table_container %}
<div class="uc pull-left m-l-5 m-r-5"><a href="{% url "assets:asset-create" %}" class="btn btn-sm btn-primary"> {% trans "Create asset" %} </a></div> <div class="uc pull-left m-l-5 m-r-5"><a href="{% url "assets:asset-create" %}" class="btn btn-sm btn-primary"> {% trans "Create asset" %} </a></div>
<div class="uc pull-left"><a href="javascript:void(0);" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#asset_import_modal"> {% trans "Import asset" %} </a></div>
<table class="table table-striped table-bordered table-hover " id="asset_list_table" > <table class="table table-striped table-bordered table-hover " id="asset_list_table" >
<thead> <thead>
<tr> <tr>
...@@ -81,6 +80,7 @@ ...@@ -81,6 +80,7 @@
</div> </div>
</div> </div>
</div> </div>
{% include 'assets/_asset_import_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
}else{ }else{
oDiv.style.display = "none"; oDiv.style.display = "none";
} }
}; //onload; } //onload;
$(document).ready(function(){ $(document).ready(function(){
var options = { var options = {
...@@ -132,31 +132,51 @@ ...@@ -132,31 +132,51 @@
], ],
ajax_url: '{% url "api-assets:asset-list" %}', ajax_url: '{% url "api-assets:asset-list" %}',
columns: [{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" }, columns: [{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" },
{data: "type_display" }, {data: "env"}, {data: "hardware"}, {data: "is_active" }, {data: "get_type_display" }, {data: "get_env_display"}, {data: "hardware"},
{data: "is_active"}, {data: "id" }], {data: "is_active" }, {data: "is_active"}, {data: "id" }],
op_html: $('#actions').html() op_html: $('#actions').html()
}; };
var table = jumpserver.initDataTable(options); var table = jumpserver.initDataTable(options);
$('.btn_export').click(function () { $('.btn_export').click(function () {
var assets = []; var assets = [];
var rows = table.rows('.selected').data(); var rows = table.rows('.selected').data();
$.each(rows, function (index, obj) { $.each(rows, function (index, obj) {
assets.push(obj.id) assets.push(obj.id)
});
$.ajax({
url: "{% url "assets:asset-export" %}",
method: 'POST',
data: JSON.stringify({assets_id: assets}),
dataType: "json",
success: function (data, textStatus) {
window.open(data.redirect)
},
error: function () {
toastr.error('Export failed');
}
})
}); });
$.ajax({
url: "{% url "assets:export-assets-xlsx" %}", $('#btn_asset_import').click(function() {
method: 'POST', var $form = $('#fm_asset_import');
data: JSON.stringify({users_id: users}), $form.find('.help-block').remove();
dataType: "json", function success (data) {
success: function (data, textStatus) { if (data.valid === false) {
window.open(data.redirect) $('<span />', {class: 'help-block text-danger'}).html(data.msg).insertAfter($('#id_users'));
}, } else {
error: function () { $('#id_created').html(data.created_info);
toastr.error('Export failed'); $('#id_created_detail').html(data.created.join(', '));
$('#id_updated').html(data.updated_info);
$('#id_updated_detail').html(data.updated.join(', '));
$('#id_failed').html(data.failed_info);
$('#id_failed_detail').html(data.failed.join(', '));
var $data_table = $('#asset_list_table').DataTable();
$data_table.ajax.reload();
} }
}) }
}); $form.ajaxSubmit({success: success});
})
}); });
</script> </script>
......
...@@ -9,6 +9,8 @@ urlpatterns = [ ...@@ -9,6 +9,8 @@ urlpatterns = [
url(r'^$', views.AssetListView.as_view(), name='asset-index'), url(r'^$', views.AssetListView.as_view(), name='asset-index'),
url(r'^asset/$', views.AssetListView.as_view(), name='asset-list'), url(r'^asset/$', views.AssetListView.as_view(), name='asset-list'),
url(r'^asset/create/$', views.AssetCreateView.as_view(), name='asset-create'), url(r'^asset/create/$', views.AssetCreateView.as_view(), name='asset-create'),
url(r'^asset/export/$', views.AssetExportView.as_view(), name='asset-export'),
url(r'^asset/import/$', views.BulkImportAssetView.as_view(), name='asset-import'),
url(r'^asset/(?P<pk>[0-9]+)/$', views.AssetDetailView.as_view(), name='asset-detail'), url(r'^asset/(?P<pk>[0-9]+)/$', views.AssetDetailView.as_view(), name='asset-detail'),
url(r'^asset/(?P<pk>[0-9]+)/update/$', views.AssetUpdateView.as_view(), name='asset-update'), url(r'^asset/(?P<pk>[0-9]+)/update/$', views.AssetUpdateView.as_view(), name='asset-update'),
url(r'^asset/(?P<pk>[0-9]+)/delete/$', views.AssetDeleteView.as_view(), name='asset-delete'), url(r'^asset/(?P<pk>[0-9]+)/delete/$', views.AssetDeleteView.as_view(), name='asset-delete'),
......
...@@ -9,6 +9,7 @@ from openpyxl import load_workbook ...@@ -9,6 +9,7 @@ from openpyxl import load_workbook
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.conf import settings from django.conf import settings
from django.db.models import Q from django.db.models import Q
from django.db import IntegrityError
from django.views.generic import TemplateView, ListView, View from django.views.generic import TemplateView, ListView, View
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
from django.urls import reverse_lazy from django.urls import reverse_lazy
...@@ -21,10 +22,11 @@ from django.utils.decorators import method_decorator ...@@ -21,10 +22,11 @@ from django.utils.decorators import method_decorator
from django.core.cache import cache from django.core.cache import cache
from django.utils import timezone from django.utils import timezone
from common.utils import int_seq from common.mixins import JSONResponseMixin
from .utils import CreateAssetTagsMiXin,UpdateAssetTagsMiXin from common.utils import get_object_or_none
from .models import Asset, AssetGroup, IDC, AdminUser, SystemUser, Tag from .utils import CreateAssetTagsMiXin, UpdateAssetTagsMiXin
from .forms import * from . import forms
from .models import Asset, AssetGroup, AdminUser, IDC, SystemUser, Tag
from .hands import AdminUserRequiredMixin from .hands import AdminUserRequiredMixin
...@@ -45,7 +47,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView): ...@@ -45,7 +47,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
class AssetCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView): class AssetCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView):
model = Asset model = Asset
tag_type = 'asset' tag_type = 'asset'
form_class = AssetCreateForm form_class = forms.AssetCreateForm
template_name = 'assets/asset_create.html' template_name = 'assets/asset_create.html'
success_url = reverse_lazy('assets:asset-list') success_url = reverse_lazy('assets:asset-list')
...@@ -71,7 +73,7 @@ class AssetCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView): ...@@ -71,7 +73,7 @@ class AssetCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView):
class AssetModalCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, ListView): class AssetModalCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, ListView):
model = Asset model = Asset
form_class = AssetCreateForm form_class = forms.AssetCreateForm
template_name = 'assets/asset_modal_update.html' template_name = 'assets/asset_modal_update.html'
success_url = reverse_lazy('assets:asset-list') success_url = reverse_lazy('assets:asset-list')
...@@ -99,7 +101,7 @@ class AssetModalCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, ListVie ...@@ -99,7 +101,7 @@ class AssetModalCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, ListVie
class AssetUpdateView(AdminUserRequiredMixin, UpdateAssetTagsMiXin, UpdateView): class AssetUpdateView(AdminUserRequiredMixin, UpdateAssetTagsMiXin, UpdateView):
model = Asset model = Asset
form_class = AssetCreateForm form_class = forms.AssetCreateForm
template_name = 'assets/asset_update.html' template_name = 'assets/asset_update.html'
success_url = reverse_lazy('assets:asset-list') success_url = reverse_lazy('assets:asset-list')
new_form = '' new_form = ''
...@@ -226,7 +228,7 @@ class AssetModalListView(AdminUserRequiredMixin, ListView): ...@@ -226,7 +228,7 @@ class AssetModalListView(AdminUserRequiredMixin, ListView):
class AssetGroupCreateView(AdminUserRequiredMixin, CreateView): class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
model = AssetGroup model = AssetGroup
form_class = AssetGroupForm form_class = forms.AssetGroupForm
template_name = 'assets/asset_group_create.html' template_name = 'assets/asset_group_create.html'
success_url = reverse_lazy('assets:asset-group-list') success_url = reverse_lazy('assets:asset-group-list')
#ordering = '-id' #ordering = '-id'
...@@ -287,7 +289,7 @@ class AssetGroupDetailView(AdminUserRequiredMixin, DetailView): ...@@ -287,7 +289,7 @@ class AssetGroupDetailView(AdminUserRequiredMixin, DetailView):
class AssetGroupUpdateView(AdminUserRequiredMixin, UpdateView): class AssetGroupUpdateView(AdminUserRequiredMixin, UpdateView):
model = AssetGroup model = AssetGroup
form_class = AssetGroupForm form_class = forms.AssetGroupForm
template_name = 'assets/asset_group_create.html' template_name = 'assets/asset_group_create.html'
success_url = reverse_lazy('assets:asset-group-list') success_url = reverse_lazy('assets:asset-group-list')
...@@ -329,7 +331,7 @@ class IDCListView(AdminUserRequiredMixin, TemplateView): ...@@ -329,7 +331,7 @@ class IDCListView(AdminUserRequiredMixin, TemplateView):
class IDCCreateView(AdminUserRequiredMixin, CreateView): class IDCCreateView(AdminUserRequiredMixin, CreateView):
model = IDC model = IDC
form_class = IDCForm form_class = forms.IDCForm
template_name = 'assets/idc_create_update.html' template_name = 'assets/idc_create_update.html'
success_url = reverse_lazy('assets:idc-list') success_url = reverse_lazy('assets:idc-list')
...@@ -351,7 +353,7 @@ class IDCCreateView(AdminUserRequiredMixin, CreateView): ...@@ -351,7 +353,7 @@ class IDCCreateView(AdminUserRequiredMixin, CreateView):
class IDCUpdateView(AdminUserRequiredMixin, UpdateView): class IDCUpdateView(AdminUserRequiredMixin, UpdateView):
model = IDC model = IDC
form_class = IDCForm form_class = forms.IDCForm
template_name = 'assets/idc_create_update.html' template_name = 'assets/idc_create_update.html'
context_object_name = 'idc' context_object_name = 'idc'
success_url = reverse_lazy('assets:idc-list') success_url = reverse_lazy('assets:idc-list')
...@@ -420,7 +422,7 @@ class AdminUserListView(AdminUserRequiredMixin, TemplateView): ...@@ -420,7 +422,7 @@ class AdminUserListView(AdminUserRequiredMixin, TemplateView):
class AdminUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView): class AdminUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
model = AdminUser model = AdminUser
form_class = AdminUserForm form_class = forms.AdminUserForm
template_name = 'assets/admin_user_create_update.html' template_name = 'assets/admin_user_create_update.html'
success_url = reverse_lazy('assets:admin-user-list') success_url = reverse_lazy('assets:admin-user-list')
...@@ -446,7 +448,7 @@ class AdminUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVie ...@@ -446,7 +448,7 @@ class AdminUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVie
class AdminUserUpdateView(AdminUserRequiredMixin, UpdateView): class AdminUserUpdateView(AdminUserRequiredMixin, UpdateView):
model = AdminUser model = AdminUser
form_class = AdminUserForm form_class = forms.AdminUserForm
template_name = 'assets/admin_user_create_update.html' template_name = 'assets/admin_user_create_update.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
...@@ -504,7 +506,7 @@ class SystemUserListView(AdminUserRequiredMixin, TemplateView): ...@@ -504,7 +506,7 @@ class SystemUserListView(AdminUserRequiredMixin, TemplateView):
class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView): class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
model = SystemUser model = SystemUser
form_class = SystemUserForm form_class = forms.SystemUserForm
template_name = 'assets/system_user_create_update.html' template_name = 'assets/system_user_create_update.html'
success_url = reverse_lazy('assets:system-user-list') success_url = reverse_lazy('assets:system-user-list')
...@@ -528,7 +530,7 @@ class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVi ...@@ -528,7 +530,7 @@ class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVi
class SystemUserUpdateView(AdminUserRequiredMixin, UpdateView): class SystemUserUpdateView(AdminUserRequiredMixin, UpdateView):
model = SystemUser model = SystemUser
form_class = SystemUserForm form_class = forms.SystemUserForm
template_name = 'assets/system_user_create_update.html' template_name = 'assets/system_user_create_update.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
...@@ -630,7 +632,7 @@ class TagsListView(AdminUserRequiredMixin, ListView): ...@@ -630,7 +632,7 @@ class TagsListView(AdminUserRequiredMixin, ListView):
class AssetTagCreateView(AdminUserRequiredMixin, CreateView): class AssetTagCreateView(AdminUserRequiredMixin, CreateView):
model = Tag model = Tag
form_class = AssetTagForm form_class = forms.AssetTagForm
template_name = 'assets/asset_tag_create.html' template_name = 'assets/asset_tag_create.html'
success_url = reverse_lazy('assets:asset-tag-list') success_url = reverse_lazy('assets:asset-tag-list')
#ordering = '-id' #ordering = '-id'
...@@ -679,7 +681,7 @@ class AssetTagDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView): ...@@ -679,7 +681,7 @@ class AssetTagDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView):
class AssetTagUpdateView(AdminUserRequiredMixin, UpdateView): class AssetTagUpdateView(AdminUserRequiredMixin, UpdateView):
model = Tag model = Tag
form_class = AssetTagForm form_class = forms.AssetTagForm
template_name = 'assets/asset_tag_create.html' template_name = 'assets/asset_tag_create.html'
success_url = reverse_lazy('assets:asset-tag-list') success_url = reverse_lazy('assets:asset-tag-list')
...@@ -707,13 +709,15 @@ class AssetTagDeleteView(AdminUserRequiredMixin, DeleteView): ...@@ -707,13 +709,15 @@ class AssetTagDeleteView(AdminUserRequiredMixin, DeleteView):
@method_decorator(csrf_exempt, name='dispatch') @method_decorator(csrf_exempt, name='dispatch')
class ExportAssetView(View): class AssetExportView(View):
@staticmethod @staticmethod
def asset_get_attr(asset, attr): def get_asset_attr(asset, attr):
if attr in ['admin_user', 'idc']: if attr in ['admin_user', 'idc']:
return getattr(asset, attr).name return getattr(asset, attr).name
if attr in ['status', 'tyoe', 'env']: elif attr in ['status', 'type', 'env']:
return getattr(asset, 'get_{}_display') return getattr(asset, 'get_{}_display'.format(attr))()
else:
return getattr(asset, attr)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
spm = request.GET.get('spm', '') spm = request.GET.get('spm', '')
...@@ -725,16 +729,15 @@ class ExportAssetView(View): ...@@ -725,16 +729,15 @@ class ExportAssetView(View):
wb = Workbook() wb = Workbook()
ws = wb.active ws = wb.active
ws.title = 'Asset' ws.title = 'Asset'
header = ['hostname', 'ip', 'port', 'admin_user', 'system_users', 'idc', header = ['hostname', 'ip', 'port', 'admin_user', 'idc', 'cpu', 'memory', 'disk',
'cpu', 'memory', 'disk', 'mac_address', 'other_ip', 'remote_card_ip', 'mac_address', 'other_ip', 'remote_card_ip', 'os', 'cabinet_no',
'os', 'cabinet_no', 'cabinet_pos', 'number', 'status', 'type', 'env', 'cabinet_pos', 'number', 'status', 'type', 'env', 'sn', 'comment']
'sn', 'comment']
ws.append(header) ws.append(header)
for asset in assets: for asset in assets:
ws.append([getattr(asset, attr) for attr in header]) ws.append([self.get_asset_attr(asset, attr) for attr in header])
filename = 'users-{}.xlsx'.format(timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S')) filename = 'assets-{}.xlsx'.format(timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S'))
response = HttpResponse(save_virtual_workbook(wb), content_type='application/vnd.ms-excel') response = HttpResponse(save_virtual_workbook(wb), content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="%s"' % filename response['Content-Disposition'] = 'attachment; filename="%s"' % filename
return response return response
...@@ -742,9 +745,89 @@ class ExportAssetView(View): ...@@ -742,9 +745,89 @@ class ExportAssetView(View):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
try: try:
assets_id = json.loads(request.body).get('assets_id', []) assets_id = json.loads(request.body).get('assets_id', [])
print(assets_id)
except ValueError: except ValueError:
return HttpResponse('Json object not valid', status=400) return HttpResponse('Json object not valid', status=400)
spm = uuid.uuid4().get_hex() spm = uuid.uuid4().get_hex()
cache.set(spm, assets_id, 300) cache.set(spm, assets_id, 300)
url = reverse('users:export-user-csv') + '?spm=%s' % spm url = reverse('assets:asset-export') + '?spm=%s' % spm
return JsonResponse({'redirect': url}) return JsonResponse({'redirect': url})
class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
form_class = forms.FileForm
def form_valid(self, form):
try:
wb = load_workbook(form.cleaned_data['file'])
ws = wb.get_active_sheet()
except Exception as e:
print(e)
data = {'valid': False, 'msg': 'Not a valid Excel file'}
return self.render_json_response(data)
rows = ws.rows
header_all = ['hostname', 'ip', 'port', 'admin_user', 'idc', 'cpu', 'memory', 'disk',
'mac_address', 'other_ip', 'remote_card_ip', 'os', 'cabinet_no',
'cabinet_pos', 'number', 'status', 'type', 'env', 'sn', 'comment']
header_min = ['hostname', 'ip', 'port', 'admin_user', 'comment']
header = [col.value for col in next(rows)]
if header not in header_all and header_min not in header:
data = {'valid': False, 'msg': 'Must be same format as template or export file'}
return self.render_json_response(data)
created = []
updated = []
failed = []
for row in rows:
asset_dict = dict(zip(header, [col.value for col in row]))
if asset_dict.get('admin_user', None):
admin_user = get_object_or_none(AdminUser, name=asset_dict['admin_user'])
asset_dict['admin_user'] = admin_user
if asset_dict.get('idc'):
idc = get_object_or_none(IDC, name=asset_dict['idc'])
asset_dict['idc'] = idc
if asset_dict.get('type'):
asset_display_type_map = dict(zip(dict(Asset.TYPE_CHOICES).values, dict(Asset.TYPE_CHOICES).keys()))
asset_type = asset_display_type_map.get(asset_dict['type'], 'Server')
asset_dict['type'] = asset_type
if asset_dict.get('status'):
asset_display_status_map = dict(zip(dict(Asset.STATUS_CHOICES).values,
dict(Asset.STATUS_CHOICES).keys()))
asset_status = asset_display_status_map.get(asset_dict['status'], 'In use')
asset_dict['status'] = asset_status
if asset_dict.get('env'):
asset_display_env_map = dict(zip(dict(Asset.ENV_CHOICES).values(),
dict(Asset.ENV_CHOICES).keys()))
asset_env = asset_display_env_map.get(asset_dict['env'], 'Prod')
asset_dict['env'] = asset_env
try:
Asset.objects.create(**asset_dict)
created.append(asset_dict['ip'])
except IntegrityError as e:
asset = Asset.objects.filter(ip=asset_dict['ip'], port=asset_dict['port'])
if not asset:
failed.append(asset_dict['ip'])
continue
asset.update(**asset_dict)
updated.append(asset_dict['ip'])
except TypeError as e:
print(e)
failed.append(asset_dict['ip'])
data = {
'created': created,
'created_info': 'Created {}'.format(len(created)),
'updated': updated,
'updated_info': 'Updated {}'.format(len(updated)),
'failed': failed,
'failed_info': 'Failed {}'.format(len(failed)),
'valid': True,
'msg': 'Created: {}. Updated: {}, Error: {}'.format(len(created), len(updated), len(failed))
}
return self.render_json_response(data)
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -99,7 +99,7 @@ $(document).ready(function(){ ...@@ -99,7 +99,7 @@ $(document).ready(function(){
users.push(obj.id) users.push(obj.id)
}); });
$.ajax({ $.ajax({
url: "{% url "users:export-user" %}", url: "{% url 'users:user-export' %}",
method: 'POST', method: 'POST',
data: JSON.stringify({users_id: users}), data: JSON.stringify({users_id: users}),
dataType: "json", dataType: "json",
......
...@@ -23,6 +23,7 @@ urlpatterns = [ ...@@ -23,6 +23,7 @@ urlpatterns = [
name='user-asset-permission-create'), name='user-asset-permission-create'),
url(r'^user/(?P<pk>[0-9]+)/assets', views.UserGrantedAssetView.as_view(), name='user-granted-asset'), url(r'^user/(?P<pk>[0-9]+)/assets', views.UserGrantedAssetView.as_view(), name='user-granted-asset'),
url(r'^user/(?P<pk>[0-9]+)/login-history', views.UserDetailView.as_view(), name='user-login-history'), url(r'^user/(?P<pk>[0-9]+)/login-history', views.UserDetailView.as_view(), name='user-login-history'),
url(r'^user/export/', views.UserExportView.as_view(), name='user-export'),
url(r'^first-login/$', views.UserFirstLoginView.as_view(), name='user-first-login'), url(r'^first-login/$', views.UserFirstLoginView.as_view(), name='user-first-login'),
url(r'^user/import/$', views.BulkImportUserView.as_view(), name='user-import'), url(r'^user/import/$', views.BulkImportUserView.as_view(), name='user-import'),
# url(r'^user/(?P<pk>[0-9]+)/assets-perm$', views.UserDetailView.as_view(), name='user-detail'), # url(r'^user/(?P<pk>[0-9]+)/assets-perm$', views.UserDetailView.as_view(), name='user-detail'),
...@@ -40,5 +41,4 @@ urlpatterns = [ ...@@ -40,5 +41,4 @@ urlpatterns = [
name='user-group-asset-permission-create'), name='user-group-asset-permission-create'),
url(r'^user-group/(?P<pk>[0-9]+)/assets', views.UserGroupGrantedAssetView.as_view(), url(r'^user-group/(?P<pk>[0-9]+)/assets', views.UserGroupGrantedAssetView.as_view(),
name='user-group-granted-asset'), name='user-group-granted-asset'),
url(r'^export/user/', views.ExportUserView.as_view(), name='export-user'),
] ]
...@@ -557,7 +557,7 @@ class BulkImportUserView(AdminUserRequiredMixin, JSONResponseMixin, FormView): ...@@ -557,7 +557,7 @@ class BulkImportUserView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
@method_decorator(csrf_exempt, name='dispatch') @method_decorator(csrf_exempt, name='dispatch')
class ExportUserView(View): class UserExportView(View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
spm = request.GET.get('spm', '') spm = request.GET.get('spm', '')
users_id = cache.get(spm) users_id = cache.get(spm)
...@@ -588,6 +588,6 @@ class ExportUserView(View): ...@@ -588,6 +588,6 @@ class ExportUserView(View):
return HttpResponse('Json object not valid', status=400) return HttpResponse('Json object not valid', status=400)
spm = uuid.uuid4().get_hex() spm = uuid.uuid4().get_hex()
cache.set(spm, users_id, 300) cache.set(spm, users_id, 300)
url = reverse('users:export-user-csv') + '?spm=%s' % spm url = reverse('users:user-export') + '?spm=%s' % spm
return JsonResponse({'redirect': url}) return JsonResponse({'redirect': url})
...@@ -2,5 +2,5 @@ ...@@ -2,5 +2,5 @@
# #
for app in users assets perms audits teminal ops;do for app in users assets perms audits teminal ops;do
rm -f $app/migrations/000* rm -f ../apps/$app/migrations/000*
done done
#!/bin/bash #!/bin/bash
# #
python ../apps/manage.py shell << EOF
from users.models import *
generate_fake()
from assets.models import *
generate_fake()
EOF
python ../apps/manage.py dbshell << EOF python ../apps/manage.py dbshell << EOF
delete from django_content_type; delete from django_content_type;
delete from auth_permission; delete from auth_permission;
EOF EOF
python ../apps/manage.py dumpdata > ../apps/fixtures/init.json python ../apps/manage.py dumpdata > ../apps/fixtures/fake.json
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment