diff --git a/apps/assets/api.py b/apps/assets/api.py
index 29e694f6f..334a7842e 100644
--- a/apps/assets/api.py
+++ b/apps/assets/api.py
@@ -2,6 +2,7 @@
from rest_framework import viewsets, generics, mixins
+
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_bulk import BulkModelViewSet, BulkDestroyAPIView
@@ -14,6 +15,7 @@ from common.utils import get_object_or_none, signer
from .hands import IsSuperUser, IsAppUser, IsValidUser, get_user_granted_assets
from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser
from . import serializers
+from .tasks import update_assets_hardware_info
class AssetViewSet(IDInFilterMixin, BulkModelViewSet):
@@ -54,29 +56,25 @@ class AssetUpdateGroupApi(generics.RetrieveUpdateAPIView):
permission_classes = (IsSuperUser,)
-## update the asset group, and add or delete the asset to the group
class AssetGroupUpdateApi(generics.RetrieveUpdateAPIView):
queryset = AssetGroup.objects.all()
serializer_class = serializers.AssetGroupUpdateSerializer
permission_classes = (IsSuperUser,)
-## update the asset group, and add or delete the system_user to the group
class AssetGroupUpdateSystemUserApi(generics.RetrieveUpdateAPIView):
queryset = AssetGroup.objects.all()
serializer_class = serializers.AssetGroupUpdateSystemUserSerializer
permission_classes = (IsSuperUser,)
-## update the IDC, and add or delete the assets to the IDC
-class IDCupdateAssetsApi(generics.RetrieveUpdateAPIView):
+class IDCUpdateAssetsApi(generics.RetrieveUpdateAPIView):
queryset = IDC.objects.all()
serializer_class = serializers.IDCUpdateAssetsSerializer
permission_classes = (IsSuperUser,)
class IDCViewSet(IDInFilterMixin, BulkModelViewSet):
- """API endpoint that allows IDC to be viewed or edited."""
queryset = IDC.objects.all()
serializer_class = serializers.IDCSerializer
permission_classes = (IsSuperUser,)
@@ -147,3 +145,14 @@ class SystemUserAuthInfoApi(generics.RetrieveAPIView):
}
return Response(data)
+
+class AssetRefreshHardwareView(generics.RetrieveAPIView):
+ queryset = Asset.objects.all()
+ serializer_class = serializers.AssetSerializer
+ permission_classes = (IsSuperUser,)
+
+ def retrieve(self, request, *args, **kwargs):
+ asset_id = kwargs.get('pk')
+ asset = get_object_or_404(Asset, pk=asset_id)
+ update_assets_hardware_info([asset])
+ return super(AssetRefreshHardwareView, self).retrieve(request, *args, **kwargs)
diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py
index 5ee3050c4..0414d03b3 100644
--- a/apps/assets/models/__init__.py
+++ b/apps/assets/models/__init__.py
@@ -6,3 +6,4 @@ from .idc import *
from .user import *
from .group import *
from .asset import *
+from .utils import *
diff --git a/apps/assets/models/utils.py b/apps/assets/models/utils.py
index ed2727cdb..b6c2d2ae6 100644
--- a/apps/assets/models/utils.py
+++ b/apps/assets/models/utils.py
@@ -2,19 +2,19 @@
# -*- coding: utf-8 -*-
#
-from . import IDC, SystemUser, AdminUser, AssetGroup, Asset, Tag
+from . import IDC, SystemUser, AdminUser, AssetGroup, Asset
-__all__ = ['initial', 'generate_fake']
+__all__ = ['init_model', 'generate_fake']
-def initial():
- for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset, Tag]:
+def init_model():
+ for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset]:
if hasattr(cls, 'initial'):
cls.initial()
def generate_fake():
- for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset, Tag]:
+ for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset]:
if hasattr(cls, 'generate_fake'):
cls.generate_fake()
diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py
index b716dc644..06cc2a9b4 100644
--- a/apps/assets/tasks.py
+++ b/apps/assets/tasks.py
@@ -53,14 +53,17 @@ def update_assets_hardware_info(assets):
asset.save()
-@shared_task(name="asset_test_ping_check")
-def asset_test_ping_check(assets):
+@shared_task
+def test_admin_user_connective(assets=None):
+ if None:
+ assets = Asset.objects.filter(type__in=['Server', 'VM'])
+ if not assets:
+ return 'No asset get'
task_tuple = (
('ping', ''),
)
- hoc = AdHocRunner(assets)
- result = hoc.run(task_tuple)
- return result['contacted'].keys(), result['dark'].keys()
+ summary, result = run_AdHoc(task_tuple, assets, record=False)
+ return summary, result
def get_assets_hardware_info(assets):
diff --git a/apps/assets/templates/assets/asset_create.html b/apps/assets/templates/assets/asset_create.html
index 5535f2b64..d19fbb893 100644
--- a/apps/assets/templates/assets/asset_create.html
+++ b/apps/assets/templates/assets/asset_create.html
@@ -17,6 +17,7 @@
{{ form.public_ip|bootstrap_horizontal }}
{{ form.port|bootstrap_horizontal }}
{{ form.type|bootstrap_horizontal }}
+ {{ form.env|bootstrap_horizontal }}
{% trans 'Group' %}
diff --git a/apps/assets/templates/assets/asset_detail.html b/apps/assets/templates/assets/asset_detail.html
index d78da68f4..c56116d61 100644
--- a/apps/assets/templates/assets/asset_detail.html
+++ b/apps/assets/templates/assets/asset_detail.html
@@ -22,6 +22,11 @@
Update
+
+
+ Delete
+
+
{% endif %}
@@ -55,6 +60,14 @@
{% trans 'IP' %}: |
{{ asset.ip }} |
+
+ {% trans 'Public IP' %}: |
+ {{ asset.public_ip }} |
+
+
+ {% trans 'Port' %}: |
+ {{ asset.port }} |
+
{% trans 'Admin user' %}: |
{% if asset.admin_user %}
@@ -63,25 +76,33 @@
None |
{% endif %}
-
- {% trans 'Other IP' %}: |
- {{ asset.other_ip }} |
-
{% trans 'Remote card IP' %}: |
{{ asset.remote_card_ip }} |
- {% trans 'Port' %}: |
- {{ asset.port }} |
+ {% trans 'IDC' %}: |
+ {{ asset.idc.name }} |
- {% trans 'Mac address' %}: |
- {{ asset.mac_addr }} |
+ {% trans 'Cabinet no' %}: |
+ {{ asset.cabinet_no }} |
+
+
+ {% trans 'Cabinet pos' %}: |
+ {{ asset.cabinet_pos }} |
+
+
+ {% trans 'Vendor' %}: |
+ {{ asset.vendor }} |
+
+
+ {% trans 'Model' %}: |
+ {{ asset.model }} |
{% trans 'CPU' %}: |
- {{ asset.cpu }} |
+ {{ asset.cpu_model }} {{ asset.cpu_count }}*{{ asset.cpu_cores }} |
{% trans 'Memory' %}: |
@@ -89,11 +110,15 @@
{% trans 'Disk' %}: |
- {{ asset.disk }} |
+ {{ asset.disk_total }} |
+
+
+ {% trans 'Platform' %}: |
+ {{ asset.platform }} |
{% trans 'OS' %}: |
- {{ asset.os }} |
+ {{ asset.os }} {{ asset.os_version }} {{ asset.os_arch }} |
{% trans 'Asset status' %}: |
@@ -163,7 +188,7 @@
{% trans 'Rrefresh hardware' %}: |
-
+
|
@@ -328,20 +353,30 @@ function updateAssetSystem(system_users) {
});
}
+function refreshAssetHardware() {
+ var the_url = "{% url 'api-assets:asset-refresh' pk=asset.id %}";
+ var success = function (data) {
+ location.reload();
+ };
+ APIUpdateAttr({
+ url: the_url,
+ success: success,
+ method: 'GET'
+ })
+}
+
$(document).ready(function () {
- $('.select2').select2()
- .on('select2:select', function(evt) {
- var data = evt.params.data;
- jumpserver.groups_selected[data.id] = data.text;
- }).on('select2:unselect', function(evt) {
- var data = evt.params.data;
- delete jumpserver.groups_selected[data.id]
- })
-})
- .on('click', '#is_active', function () {
- var the_url = '{% url "api-assets:asset-detail" pk=asset.id %}';
- var checked = $(this).prop('checked');
+ $('.select2').select2().on('select2:select', function(evt) {
+ var data = evt.params.data;
+ jumpserver.groups_selected[data.id] = data.text;
+ }).on('select2:unselect', function(evt) {
+ var data = evt.params.data;
+ delete jumpserver.groups_selected[data.id]
+ })
+}).on('click', '#is_active', function () {
+ var the_url = '{% url "api-assets:asset-detail" pk=asset.id %}';
+ var checked = $(this).prop('checked');
var body = {
'is_active': checked
};
@@ -357,21 +392,19 @@ $(document).ready(function () {
}else{
$(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('False');
}
-})
- .on('click', '#btn_add_user_group', function () {
- if (Object.keys(jumpserver.groups_selected).length === 0) {
- return false;
- }
- var groups = $('.bdg_group').map(function() {
- return $(this).data('gid');
- }).get();
- $.map(jumpserver.groups_selected, function(value, index) {
- groups.push(parseInt(index));
- $('#opt_' + index).remove();
- });
- updateAssetGroups(groups)
-})
- .on('click', '.btn_leave_group', function() {
+}).on('click', '#btn_add_user_group', function () {
+ if (Object.keys(jumpserver.groups_selected).length === 0) {
+ return false;
+ }
+ var groups = $('.bdg_group').map(function() {
+ return $(this).data('gid');
+ }).get();
+ $.map(jumpserver.groups_selected, function(value, index) {
+ groups.push(parseInt(index));
+ $('#opt_' + index).remove();
+ });
+ updateAssetGroups(groups)
+}).on('click', '.btn_leave_group', function() {
var $this = $(this);
var $tr = $this.closest('tr');
var $badge = $tr.find('.bdg_group');
@@ -385,36 +418,43 @@ $(document).ready(function () {
return $(this).data('gid');
}).get();
updateAssetGroups(groups)
-})
- .on('click', '.btn-system-user', function () {
- if (Object.keys(jumpserver.groups_selected).length === 0) {
- return false;
- }
- var system_users = $('.bdg_group').map(function() {
- return $(this).data('sid');
- }).get();
- $.map(jumpserver.groups_selected, function(value, index) {
- system_users.push(parseInt(index));
- $('#opt_' + index).remove();
- });
- updateAssetSystem(system_users)
+}).on('click', '.btn-system-user', function () {
+ if (Object.keys(jumpserver.groups_selected).length === 0) {
+ return false;
+ }
+ var system_users = $('.bdg_group').map(function() {
+ return $(this).data('sid');
+ }).get();
+ $.map(jumpserver.groups_selected, function(value, index) {
+ system_users.push(parseInt(index));
+ $('#opt_' + index).remove();
+ });
+ updateAssetSystem(system_users)
-})
- .on('click', '.btn_leave_system', function () {
- var $this = $(this);
- var $tr = $this.closest('tr');
- var $badge = $tr.find('.bdg_group');
- var sid = $badge.data('sid');
- var name = $badge.html() || $badge.text();
- $('#groups_selected').append(
- ''
- );
- $tr.remove();
- var system_users = $('.bdg_group').map(function () {
- return $(this).data('sid');
- }).get();
- updateAssetSystem(system_users)
+}).on('click', '.btn_leave_system', function () {
+ var $this = $(this);
+ var $tr = $this.closest('tr');
+ var $badge = $tr.find('.bdg_group');
+ var sid = $badge.data('sid');
+ var name = $badge.html() || $badge.text();
+ $('#groups_selected').append(
+ ''
+ );
+ $tr.remove();
+ var system_users = $('.bdg_group').map(function () {
+ return $(this).data('sid');
+ }).get();
+ updateAssetSystem(system_users)
+}).on('click', '.btn-delete-asset', function () {
+ var $this = $(this);
+ var name = "{{ asset.hostname }}";
+ var uid = "{{ asset.id }}";
+ var the_url = '{% url "api-assets:asset-detail" pk=99991937 %}'.replace('99991937', uid);
+ var redirect_url = "{% url 'assets:asset-list' %}";
+ objectDelete($this, name, the_url, redirect_url);
+}).on('click', '.btn-refresh-asset', function () {
+ refreshAssetHardware()
})
diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py
index 0abe9db6f..ec1c8433c 100644
--- a/apps/assets/urls/api_urls.py
+++ b/apps/assets/urls/api_urls.py
@@ -22,6 +22,9 @@ urlpatterns = [
url(r'^v1/assets/(?P\d+)/groups/$',
api.AssetUpdateGroupApi.as_view(), name='asset-update-group'),
+ url(r'^v1/assets/(?P\d+)/refresh/$',
+ api.AssetRefreshHardwareView.as_view(), name='asset-refresh'),
+
url(r'^v1/assets/(?P\d+)/system-users/$',
api.SystemUserUpdateApi.as_view(), name='asset-update-system-users'),
@@ -42,7 +45,7 @@ urlpatterns = [
# update the IDC, and add or delete the assets to the IDC
url(r'^v1/idc/(?P\d+)/assets/$',
- api.IDCupdateAssetsApi.as_view(), name='idc-update-assets'),
+ api.IDCUpdateAssetsApi.as_view(), name='idc-update-assets'),
]
diff --git a/apps/assets/views.py b/apps/assets/views.py
deleted file mode 100644
index f5bbcd216..000000000
--- a/apps/assets/views.py
+++ /dev/null
@@ -1,708 +0,0 @@
-# coding:utf-8
-from __future__ import absolute_import, unicode_literals
-import json
-import uuid
-
-from openpyxl import Workbook
-from openpyxl.writer.excel import save_virtual_workbook
-from openpyxl import load_workbook
-from django.utils.translation import ugettext as _
-from django.conf import settings
-from django.db.models import Q
-from django.db import transaction
-from django.db import IntegrityError
-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.contrib.messages.views import SuccessMessageMixin
-from django.views.generic.detail import DetailView, SingleObjectMixin
-from django.shortcuts import get_object_or_404, reverse, redirect
-from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
-from django.views.decorators.csrf import csrf_protect, csrf_exempt
-from django.utils.decorators import method_decorator
-from django.core.cache import cache
-from django.utils import timezone
-from django.contrib.auth.mixins import LoginRequiredMixin
-
-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 .hands import AdminUserRequiredMixin
-from .tasks import update_assets_hardware_info
-
-
-class AssetListView(AdminUserRequiredMixin, TemplateView):
- template_name = 'assets/asset_list.html'
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': 'Assets',
- 'action': 'asset list',
- 'groups': AssetGroup.objects.all(),
- 'system_users': SystemUser.objects.all(),
- }
- kwargs.update(context)
- return super(AssetListView, self).get_context_data(**kwargs)
-
-
-class UserAssetListView(LoginRequiredMixin, TemplateView):
- template_name = 'assets/user_asset_list.html'
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': 'Assets',
- 'action': 'asset list',
- 'system_users': SystemUser.objects.all(),
- }
- kwargs.update(context)
- return super(UserAssetListView, self).get_context_data(**kwargs)
-
-
-class AssetCreateView(AdminUserRequiredMixin, CreateView):
- model = Asset
- form_class = forms.AssetCreateForm
- template_name = 'assets/asset_create.html'
- success_url = reverse_lazy('assets:asset-list')
-
- def form_valid(self, form):
- self.asset = asset = form.save()
- asset.created_by = self.request.user.username or 'Admin'
- asset.save()
- return super(AssetCreateView, self).form_valid(form)
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': 'Assets',
- 'action': 'Create asset',
- }
- kwargs.update(context)
- return super(AssetCreateView, self).get_context_data(**kwargs)
-
- def get_success_url(self):
- update_assets_hardware_info.delay([self.asset])
- return super(AssetCreateView, self).get_success_url()
-
-
-class AssetModalCreateView(AdminUserRequiredMixin, ListView):
- model = Asset
- form_class = forms.AssetCreateForm
- template_name = 'assets/asset_modal_update.html'
- success_url = reverse_lazy('assets:asset-list')
-
- def get_queryset(self):
- self.queryset = super(AssetModalCreateView,self).get_queryset()
- self.s = self.request.GET.get('plain_id_lists')
- if "," in str(self.s):
- self.plain_id_lists = [int(x) for x in self.s.split(',')]
- else:
- self.plain_id_lists = [self.s]
- return self.queryset
-
- def get_context_data(self, **kwargs):
- asset_on_list = Asset.objects.filter(id__in = self.plain_id_lists)
- context = {
- 'app': 'Assets',
- 'action': 'Bulk Update asset',
- 'assets_on_list': asset_on_list,
- 'assets_count': len(asset_on_list),
- 'plain_id_lists':self.s,
- }
- kwargs.update(context)
- return super(AssetModalCreateView, self).get_context_data(**kwargs)
-
-
-class AssetUpdateView(AdminUserRequiredMixin, UpdateView):
- model = Asset
- form_class = forms.AssetUpdateForm
- template_name = 'assets/asset_update.html'
- success_url = reverse_lazy('assets:asset-list')
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': 'Assets',
- 'action': 'Update asset',
- }
- kwargs.update(context)
- return super(AssetUpdateView, self).get_context_data(**kwargs)
-
- def form_invalid(self, form):
- print(form.errors)
- return super(AssetUpdateView, self).form_invalid(form)
-
-
-class AssetDeleteView(AdminUserRequiredMixin, DeleteView):
- model = Asset
- template_name = 'assets/delete_confirm.html'
- success_url = reverse_lazy('assets:asset-list')
-
-
-class AssetDetailView(DetailView):
- model = Asset
- context_object_name = 'asset'
- template_name = 'assets/asset_detail.html'
-
- def get_context_data(self, **kwargs):
- asset_groups = self.object.groups.all()
- system_users = self.object.system_users.all()
- context = {
- 'app': 'Assets',
- 'action': 'Asset detail',
- 'asset_groups_remain': [asset_group for asset_group in AssetGroup.objects.all()
- if asset_group not in asset_groups],
- 'asset_groups': asset_groups,
- 'system_users_remain': [system_user for system_user in SystemUser.objects.all()
- if system_user not in system_users],
- 'system_users': system_users,
- }
- kwargs.update(context)
- return super(AssetDetailView, self).get_context_data(**kwargs)
-
-
-class AssetModalListView(AdminUserRequiredMixin, ListView):
- paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
- model = Asset
- context_object_name = 'asset_modal_list'
- template_name = 'assets/asset_modal_list.html'
-
- def get_context_data(self, **kwargs):
- group_id = self.request.GET.get('group_id')
- plain_id_lists = self.request.GET.get('plain_id_lists')
- self.s = self.request.GET.get('plain_id_lists')
- assets = Asset.objects.all()
- if "," in str(self.s):
- self.plain_id_lists = [int(x) for x in self.s.split(',')]
- else:
- self.plain_id_lists = [self.s]
-
- if plain_id_lists:
- if "," in str(self.s):
- plain_id_lists = [int(x) for x in self.s.split(',')]
- else:
- plain_id_lists = [int(self.s)]
- context = {
- 'all_assets': plain_id_lists,
- }
- kwargs.update(context)
- if group_id:
- group = AssetGroup.objects.get(id=group_id)
- context = {
- 'all_assets': [x.id for x in group.assets.all()],
- 'assets': assets
- }
- kwargs.update(context)
- else:
- context = {
- 'assets': assets
- }
- kwargs.update(context)
- return super(AssetModalListView, self).get_context_data(**kwargs)
-
-
-class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
- model = AssetGroup
- form_class = forms.AssetGroupForm
- template_name = 'assets/asset_group_create.html'
- success_url = reverse_lazy('assets:asset-group-list')
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Assets'),
- 'action': _('Create asset group'),
- 'assets_count': 0,
- }
- kwargs.update(context)
- return super(AssetGroupCreateView, self).get_context_data(**kwargs)
-
- def form_valid(self, form):
- asset_group = form.save()
- assets_id_list = self.request.POST.getlist('assets', [])
- assets = [get_object_or_404(Asset, id=int(asset_id))
- for asset_id in assets_id_list]
- asset_group.created_by = self.request.user.username or 'Admin'
- asset_group.assets.add(*tuple(assets))
- asset_group.save()
- return super(AssetGroupCreateView, self).form_valid(form)
-
-
-class AssetGroupListView(AdminUserRequiredMixin, TemplateView):
- template_name = 'assets/asset_group_list.html'
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Assets'),
- 'action': _('Asset group list'),
- 'assets': Asset.objects.all(),
- 'system_users': SystemUser.objects.all(),
- 'keyword': self.request.GET.get('keyword', '')
- }
- kwargs.update(context)
- return super(AssetGroupListView, self).get_context_data(**kwargs)
-
-
-class AssetGroupDetailView(AdminUserRequiredMixin, DetailView):
- model = AssetGroup
- template_name = 'assets/asset_group_detail.html'
- context_object_name = 'asset_group'
-
- def get_context_data(self, **kwargs):
- assets_remain = Asset.objects.exclude(id__in=self.object.assets.all())
- system_users = self.object.system_users.all()
- system_users_remain = SystemUser.objects.exclude(id__in=system_users)
- context = {
- 'app': _('Assets'),
- 'action': _('Asset group detail'),
- 'assets_remain': assets_remain,
- 'assets': [asset for asset in Asset.objects.all()
- if asset not in assets_remain],
- 'system_users': system_users,
- 'system_users_remain': system_users_remain,
- }
- kwargs.update(context)
- return super(AssetGroupDetailView, self).get_context_data(**kwargs)
-
-
-class AssetGroupUpdateView(AdminUserRequiredMixin, UpdateView):
- model = AssetGroup
- form_class = forms.AssetGroupForm
- template_name = 'assets/asset_group_create.html'
- success_url = reverse_lazy('assets:asset-group-list')
-
- def get(self, request, *args, **kwargs):
- self.object = self.get_object(queryset=AssetGroup.objects.all())
- return super(AssetGroupUpdateView, self).get(request, *args, **kwargs)
-
- def get_context_data(self, **kwargs):
- assets_all = self.object.assets.all()
- context = {
- 'app': _('Assets'),
- 'action': _('Create asset group'),
- 'assets_on_list': assets_all,
- 'assets_count': len(assets_all),
- 'group_id': self.object.id,
- }
- kwargs.update(context)
- return super(AssetGroupUpdateView, self).get_context_data(**kwargs)
-
-
-class AssetGroupDeleteView(AdminUserRequiredMixin, DeleteView):
- template_name = 'assets/delete_confirm.html'
- model = AssetGroup
- success_url = reverse_lazy('assets:asset-group-list')
-
-
-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')
-
-
-class AdminUserListView(AdminUserRequiredMixin, TemplateView):
- model = AdminUser
- template_name = 'assets/admin_user_list.html'
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Assets'),
- 'action': _('Admin user list'),
- }
- kwargs.update(context)
- return super(AdminUserListView, self).get_context_data(**kwargs)
-
-
-class AdminUserCreateView(AdminUserRequiredMixin,
- SuccessMessageMixin,
- CreateView):
- model = AdminUser
- form_class = forms.AdminUserForm
- template_name = 'assets/admin_user_create_update.html'
- success_url = reverse_lazy('assets:admin-user-list')
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': 'assets',
- 'action': 'Create admin user'
- }
- kwargs.update(context)
- return super(AdminUserCreateView, self).get_context_data(**kwargs)
-
- def get_success_message(self, cleaned_data):
- success_message = _(
- 'Create admin user %s successfully.' % (
- reverse_lazy('assets:admin-user-detail',
- kwargs={'pk': self.object.pk}),
- self.object.name,
- ))
- return success_message
-
- def form_invalid(self, form):
- return super(AdminUserCreateView, self).form_invalid(form)
-
-
-class AdminUserUpdateView(AdminUserRequiredMixin, UpdateView):
- model = AdminUser
- form_class = forms.AdminUserForm
- template_name = 'assets/admin_user_create_update.html'
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': 'assets',
- 'action': 'Update admin user'
- }
- kwargs.update(context)
- return super(AdminUserUpdateView, self).get_context_data(**kwargs)
-
- def get_success_url(self):
- success_url = reverse_lazy('assets:admin-user-detail',
- kwargs={'pk': self.object.pk})
- return success_url
-
-
-class AdminUserDetailView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
- paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
- template_name = 'assets/admin_user_detail.html'
- context_object_name = 'admin_user'
-
- def get(self, request, *args, **kwargs):
- self.object = self.get_object(queryset=AdminUser.objects.all())
- return super(AdminUserDetailView, self).get(request, *args, **kwargs)
-
- def get_queryset(self):
- return self.object.assets.all()
-
- def get_context_data(self, **kwargs):
- asset_groups = AssetGroup.objects.all()
- assets = self.get_queryset()
- context = {
- 'app': 'assets',
- 'action': 'Admin user detail',
- 'assets_remain': [asset for asset in Asset.objects.all() if asset not in assets],
- 'asset_groups': asset_groups,
- }
- kwargs.update(context)
- return super(AdminUserDetailView, self).get_context_data(**kwargs)
-
-
-class AdminUserDeleteView(AdminUserRequiredMixin, DeleteView):
- model = AdminUser
- template_name = 'assets/delete_confirm.html'
- success_url = reverse_lazy('assets:admin-user-list')
-
-
-class SystemUserListView(AdminUserRequiredMixin, TemplateView):
- template_name = 'assets/system_user_list.html'
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Assets'),
- 'action': _('System user list'),
- }
- kwargs.update(context)
- return super(SystemUserListView, self).get_context_data(**kwargs)
-
-
-class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
- model = SystemUser
- form_class = forms.SystemUserForm
- template_name = 'assets/system_user_create.html'
- success_url = reverse_lazy('assets:system-user-list')
-
- @transaction.atomic
- def post(self, request, *args, **kwargs):
- return super(SystemUserCreateView, self).post(request, *args, **kwargs)
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Assets'),
- 'action': _('Create system user'),
- }
- kwargs.update(context)
- return super(SystemUserCreateView, self).get_context_data(**kwargs)
-
- def form_invalid(self, form):
- print(form.errors)
- return super(SystemUserCreateView, self).form_invalid(form)
-
- def get_success_message(self, cleaned_data):
- success_message = _('Create system user %s successfully.' %
- (
- reverse_lazy('assets:system-user-detail', kwargs={'pk': self.object.pk}),
- self.object.name,
- ))
-
- return success_message
-
-
-class SystemUserUpdateView(AdminUserRequiredMixin, UpdateView):
- model = SystemUser
- form_class = forms.SystemUserForm
- template_name = 'assets/system_user_update.html'
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Assets'),
- 'action': _('Update system user')
- }
- kwargs.update(context)
- return super(SystemUserUpdateView, self).get_context_data(**kwargs)
-
- def get_success_url(self):
- success_url = reverse_lazy('assets:system-user-detail', kwargs={'pk': self.object.pk})
- return success_url
-
-
-class SystemUserDetailView(AdminUserRequiredMixin, DetailView):
- template_name = 'assets/system_user_detail.html'
- context_object_name = 'system_user'
- model = SystemUser
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Assets'),
- 'action': _('System user detail')
- }
- kwargs.update(context)
- return super(SystemUserDetailView, self).get_context_data(**kwargs)
-
-
-class SystemUserDeleteView(AdminUserRequiredMixin, DeleteView):
- model = SystemUser
- template_name = 'assets/delete_confirm.html'
- success_url = reverse_lazy('assets:system-user-list')
-
-
-class SystemUserAssetView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
- paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
- template_name = 'assets/system_user_asset.html'
- context_object_name = 'system_user'
-
- def get(self, request, *args, **kwargs):
- self.object = self.get_object(queryset=SystemUser.objects.all())
- return super(SystemUserAssetView, self).get(request, *args, **kwargs)
-
- def get_asset_groups(self):
- return self.object.asset_groups.all()
-
- # Todo: queryset default order by connectivity, need ops support
- def get_queryset(self):
- return list(self.object.get_assets())
-
- def get_context_data(self, **kwargs):
- asset_groups = self.get_asset_groups()
- assets = self.get_queryset()
- context = {
- 'app': 'assets',
- 'action': 'System user asset',
- 'assets_remain': [asset for asset in Asset.objects.all() if asset not in assets],
- 'asset_groups': asset_groups,
- 'asset_groups_remain': [asset_group for asset_group in AssetGroup.objects.all()
- if asset_group not in asset_groups]
- }
- kwargs.update(context)
- return super(SystemUserAssetView, self).get_context_data(**kwargs)
-
-
-@method_decorator(csrf_exempt, name='dispatch')
-class AssetExportView(View):
- @staticmethod
- def get_asset_attr(asset, attr):
- if attr in ['admin_user', 'idc']:
- return getattr(asset, attr).name
- elif attr in ['status', 'type', 'env']:
- return getattr(asset, 'get_{}_display'.format(attr))()
- else:
- return getattr(asset, attr)
-
- def get(self, request, *args, **kwargs):
- spm = request.GET.get('spm', '')
- assets_id = cache.get(spm)
- if not assets_id and not isinstance(assets_id, list):
- return HttpResponse('May be expired', status=404)
-
- assets = Asset.objects.filter(id__in=assets_id)
- wb = Workbook()
- ws = wb.active
- ws.title = 'Asset'
- header = ['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']
- ws.append(header)
-
- for asset in assets:
- ws.append([self.get_asset_attr(asset, attr) for attr in header])
-
- filename = 'assets-{}.xlsx'.format(timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S'))
- response = HttpResponse(save_virtual_workbook(wb), content_type='applications/vnd.ms-excel')
- response['Content-Disposition'] = 'attachment; filename="%s"' % filename
- return response
-
- def post(self, request, *args, **kwargs):
- try:
- assets_id = json.loads(request.body).get('assets_id', [])
- print(assets_id)
- except ValueError:
- return HttpResponse('Json object not valid', status=400)
- spm = uuid.uuid4().get_hex()
- cache.set(spm, assets_id, 300)
- url = reverse_lazy('assets:asset-export') + '?spm=%s' % spm
- 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 not set(header).issubset(set(header_all)) and not set(header).issuperset(set(header_min)):
- 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)
diff --git a/apps/assets/views/__init__.py b/apps/assets/views/__init__.py
new file mode 100644
index 000000000..7cf30acbe
--- /dev/null
+++ b/apps/assets/views/__init__.py
@@ -0,0 +1,7 @@
+# coding:utf-8
+from .asset import *
+from .group import *
+from .idc import *
+from .system_user import *
+from .admin_user import *
+
diff --git a/apps/assets/views/admin_user.py b/apps/assets/views/admin_user.py
new file mode 100644
index 000000000..02977efd5
--- /dev/null
+++ b/apps/assets/views/admin_user.py
@@ -0,0 +1,112 @@
+# coding:utf-8
+from __future__ import absolute_import, unicode_literals
+from django.utils.translation import ugettext as _
+from django.conf import settings
+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.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 ..hands import AdminUserRequiredMixin
+
+__all__ = ['AdminUserCreateView', 'AdminUserDetailView',
+ 'AdminUserDeleteView', 'AdminUserListView',
+ 'AdminUserUpdateView',
+ ]
+
+
+class AdminUserListView(AdminUserRequiredMixin, TemplateView):
+ model = AdminUser
+ template_name = 'assets/admin_user_list.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Assets'),
+ 'action': _('Admin user list'),
+ }
+ kwargs.update(context)
+ return super(AdminUserListView, self).get_context_data(**kwargs)
+
+
+class AdminUserCreateView(AdminUserRequiredMixin,
+ SuccessMessageMixin,
+ CreateView):
+ model = AdminUser
+ form_class = forms.AdminUserForm
+ template_name = 'assets/admin_user_create_update.html'
+ success_url = reverse_lazy('assets:admin-user-list')
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': 'assets',
+ 'action': 'Create admin user'
+ }
+ kwargs.update(context)
+ return super(AdminUserCreateView, self).get_context_data(**kwargs)
+
+ def get_success_message(self, cleaned_data):
+ success_message = _(
+ 'Create admin user %s successfully.' % (
+ reverse_lazy('assets:admin-user-detail',
+ kwargs={'pk': self.object.pk}),
+ self.object.name,
+ ))
+ return success_message
+
+ def form_invalid(self, form):
+ return super(AdminUserCreateView, self).form_invalid(form)
+
+
+class AdminUserUpdateView(AdminUserRequiredMixin, UpdateView):
+ model = AdminUser
+ form_class = forms.AdminUserForm
+ template_name = 'assets/admin_user_create_update.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': 'assets',
+ 'action': 'Update admin user'
+ }
+ kwargs.update(context)
+ return super(AdminUserUpdateView, self).get_context_data(**kwargs)
+
+ def get_success_url(self):
+ success_url = reverse_lazy('assets:admin-user-detail',
+ kwargs={'pk': self.object.pk})
+ return success_url
+
+
+class AdminUserDetailView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
+ paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
+ template_name = 'assets/admin_user_detail.html'
+ context_object_name = 'admin_user'
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object(queryset=AdminUser.objects.all())
+ return super(AdminUserDetailView, self).get(request, *args, **kwargs)
+
+ def get_queryset(self):
+ return self.object.assets.all()
+
+ def get_context_data(self, **kwargs):
+ asset_groups = AssetGroup.objects.all()
+ assets = self.get_queryset()
+ context = {
+ 'app': 'assets',
+ 'action': 'Admin user detail',
+ 'assets_remain': [asset for asset in Asset.objects.all() if asset not in assets],
+ 'asset_groups': asset_groups,
+ }
+ kwargs.update(context)
+ return super(AdminUserDetailView, self).get_context_data(**kwargs)
+
+
+class AdminUserDeleteView(AdminUserRequiredMixin, DeleteView):
+ model = AdminUser
+ template_name = 'assets/delete_confirm.html'
+ success_url = reverse_lazy('assets:admin-user-list')
+
+
diff --git a/apps/assets/views/asset.py b/apps/assets/views/asset.py
new file mode 100644
index 000000000..0514ca467
--- /dev/null
+++ b/apps/assets/views/asset.py
@@ -0,0 +1,331 @@
+# coding:utf-8
+from __future__ import absolute_import, unicode_literals
+import json
+import uuid
+
+from openpyxl import Workbook
+from openpyxl.writer.excel import save_virtual_workbook
+from openpyxl import load_workbook
+from django.conf import settings
+from django.db import IntegrityError
+from django.urls import reverse
+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 django.http import HttpResponse, JsonResponse, HttpResponseRedirect
+from django.views.decorators.csrf import csrf_protect, csrf_exempt
+from django.utils.decorators import method_decorator
+from django.core.cache import cache
+from django.utils import timezone
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.shortcuts import get_object_or_404, redirect
+
+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 ..hands import AdminUserRequiredMixin
+from ..tasks import update_assets_hardware_info
+
+
+__all__ = ['AssetListView', 'AssetCreateView', 'AssetUpdateView',
+ 'UserAssetListView', 'AssetModalCreateView', 'AssetDetailView',
+ 'AssetModalListView', 'AssetDeleteView', 'AssetExportView',
+ 'BulkImportAssetView',
+ ]
+
+
+class AssetListView(AdminUserRequiredMixin, TemplateView):
+ template_name = 'assets/asset_list.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': 'Assets',
+ 'action': 'asset list',
+ 'groups': AssetGroup.objects.all(),
+ 'system_users': SystemUser.objects.all(),
+ }
+ kwargs.update(context)
+ return super(AssetListView, self).get_context_data(**kwargs)
+
+
+class UserAssetListView(LoginRequiredMixin, TemplateView):
+ template_name = 'assets/user_asset_list.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': 'Assets',
+ 'action': 'asset list',
+ 'system_users': SystemUser.objects.all(),
+ }
+ kwargs.update(context)
+ return super(UserAssetListView, self).get_context_data(**kwargs)
+
+
+class AssetCreateView(AdminUserRequiredMixin, CreateView):
+ model = Asset
+ form_class = forms.AssetCreateForm
+ template_name = 'assets/asset_create.html'
+ success_url = reverse_lazy('assets:asset-list')
+
+ def form_valid(self, form):
+ self.asset = asset = form.save()
+ asset.created_by = self.request.user.username or 'Admin'
+ asset.date_created = timezone.now()
+ asset.save()
+ return super(AssetCreateView, self).form_valid(form)
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': 'Assets',
+ 'action': 'Create asset',
+ }
+ kwargs.update(context)
+ return super(AssetCreateView, self).get_context_data(**kwargs)
+
+ def get_success_url(self):
+ update_assets_hardware_info.delay([self.asset])
+ return super(AssetCreateView, self).get_success_url()
+
+
+class AssetModalCreateView(AdminUserRequiredMixin, ListView):
+ model = Asset
+ form_class = forms.AssetCreateForm
+ template_name = 'assets/asset_modal_update.html'
+ success_url = reverse_lazy('assets:asset-list')
+
+ def get_queryset(self):
+ self.queryset = super(AssetModalCreateView,self).get_queryset()
+ self.s = self.request.GET.get('plain_id_lists')
+ if "," in str(self.s):
+ self.plain_id_lists = [int(x) for x in self.s.split(',')]
+ else:
+ self.plain_id_lists = [self.s]
+ return self.queryset
+
+ def get_context_data(self, **kwargs):
+ asset_on_list = Asset.objects.filter(id__in = self.plain_id_lists)
+ context = {
+ 'app': 'Assets',
+ 'action': 'Bulk Update asset',
+ 'assets_on_list': asset_on_list,
+ 'assets_count': len(asset_on_list),
+ 'plain_id_lists':self.s,
+ }
+ kwargs.update(context)
+ return super(AssetModalCreateView, self).get_context_data(**kwargs)
+
+
+class AssetUpdateView(AdminUserRequiredMixin, UpdateView):
+ model = Asset
+ form_class = forms.AssetUpdateForm
+ template_name = 'assets/asset_update.html'
+ success_url = reverse_lazy('assets:asset-list')
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': 'Assets',
+ 'action': 'Update asset',
+ }
+ kwargs.update(context)
+ return super(AssetUpdateView, self).get_context_data(**kwargs)
+
+ def form_invalid(self, form):
+ print(form.errors)
+ return super(AssetUpdateView, self).form_invalid(form)
+
+
+class AssetDeleteView(AdminUserRequiredMixin, DeleteView):
+ model = Asset
+ template_name = 'assets/delete_confirm.html'
+ success_url = reverse_lazy('assets:asset-list')
+
+
+class AssetDetailView(DetailView):
+ model = Asset
+ context_object_name = 'asset'
+ template_name = 'assets/asset_detail.html'
+
+ def get_context_data(self, **kwargs):
+ asset_groups = self.object.groups.all()
+ system_users = self.object.system_users.all()
+ context = {
+ 'app': 'Assets',
+ 'action': 'Asset detail',
+ 'asset_groups_remain': [asset_group for asset_group in AssetGroup.objects.all()
+ if asset_group not in asset_groups],
+ 'asset_groups': asset_groups,
+ 'system_users_remain': [system_user for system_user in SystemUser.objects.all()
+ if system_user not in system_users],
+ 'system_users': system_users,
+ }
+ kwargs.update(context)
+ return super(AssetDetailView, self).get_context_data(**kwargs)
+
+
+class AssetModalListView(AdminUserRequiredMixin, ListView):
+ paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
+ model = Asset
+ context_object_name = 'asset_modal_list'
+ template_name = 'assets/asset_modal_list.html'
+
+ def get_context_data(self, **kwargs):
+ group_id = self.request.GET.get('group_id')
+ plain_id_lists = self.request.GET.get('plain_id_lists')
+ self.s = self.request.GET.get('plain_id_lists')
+ assets = Asset.objects.all()
+ if "," in str(self.s):
+ self.plain_id_lists = [int(x) for x in self.s.split(',')]
+ else:
+ self.plain_id_lists = [self.s]
+
+ if plain_id_lists:
+ if "," in str(self.s):
+ plain_id_lists = [int(x) for x in self.s.split(',')]
+ else:
+ plain_id_lists = [int(self.s)]
+ context = {
+ 'all_assets': plain_id_lists,
+ }
+ kwargs.update(context)
+ if group_id:
+ group = AssetGroup.objects.get(id=group_id)
+ context = {
+ 'all_assets': [x.id for x in group.assets.all()],
+ 'assets': assets
+ }
+ kwargs.update(context)
+ else:
+ context = {
+ 'assets': assets
+ }
+ kwargs.update(context)
+ return super(AssetModalListView, self).get_context_data(**kwargs)
+
+
+@method_decorator(csrf_exempt, name='dispatch')
+class AssetExportView(View):
+ @staticmethod
+ def get_asset_attr(asset, attr):
+ if attr in ['admin_user', 'idc']:
+ return getattr(asset, attr).name
+ elif attr in ['status', 'type', 'env']:
+ return getattr(asset, 'get_{}_display'.format(attr))()
+ else:
+ return getattr(asset, attr)
+
+ def get(self, request, *args, **kwargs):
+ spm = request.GET.get('spm', '')
+ assets_id = cache.get(spm)
+ if not assets_id and not isinstance(assets_id, list):
+ return HttpResponse('May be expired', status=404)
+
+ assets = Asset.objects.filter(id__in=assets_id)
+ wb = Workbook()
+ ws = wb.active
+ ws.title = 'Asset'
+ header = ['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']
+ ws.append(header)
+
+ for asset in assets:
+ ws.append([self.get_asset_attr(asset, attr) for attr in header])
+
+ filename = 'assets-{}.xlsx'.format(timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S'))
+ response = HttpResponse(save_virtual_workbook(wb), content_type='applications/vnd.ms-excel')
+ response['Content-Disposition'] = 'attachment; filename="%s"' % filename
+ return response
+
+ def post(self, request, *args, **kwargs):
+ try:
+ assets_id = json.loads(request.body).get('assets_id', [])
+ print(assets_id)
+ except ValueError:
+ return HttpResponse('Json object not valid', status=400)
+ spm = uuid.uuid4().get_hex()
+ cache.set(spm, assets_id, 300)
+ url = reverse_lazy('assets:asset-export') + '?spm=%s' % spm
+ 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 not set(header).issubset(set(header_all)) and not set(header).issuperset(set(header_min)):
+ 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)
+
+
diff --git a/apps/assets/views/group.py b/apps/assets/views/group.py
new file mode 100644
index 000000000..01d341168
--- /dev/null
+++ b/apps/assets/views/group.py
@@ -0,0 +1,111 @@
+# 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 django.shortcuts import get_object_or_404, reverse, redirect
+
+from .. import forms
+from ..models import Asset, AssetGroup, AdminUser, IDC, SystemUser
+from ..hands import AdminUserRequiredMixin
+
+
+__all__ = ['AssetGroupCreateView', 'AssetGroupDetailView',
+ 'AssetGroupUpdateView', 'AssetGroupListView',
+ 'AssetGroupDeleteView',
+ ]
+
+
+class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
+ model = AssetGroup
+ form_class = forms.AssetGroupForm
+ template_name = 'assets/asset_group_create.html'
+ success_url = reverse_lazy('assets:asset-group-list')
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Assets'),
+ 'action': _('Create asset group'),
+ 'assets_count': 0,
+ }
+ kwargs.update(context)
+ return super(AssetGroupCreateView, self).get_context_data(**kwargs)
+
+ def form_valid(self, form):
+ asset_group = form.save()
+ assets_id_list = self.request.POST.getlist('assets', [])
+ assets = [get_object_or_404(Asset, id=int(asset_id))
+ for asset_id in assets_id_list]
+ asset_group.created_by = self.request.user.username or 'Admin'
+ asset_group.assets.add(*tuple(assets))
+ asset_group.save()
+ return super(AssetGroupCreateView, self).form_valid(form)
+
+
+class AssetGroupListView(AdminUserRequiredMixin, TemplateView):
+ template_name = 'assets/asset_group_list.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Assets'),
+ 'action': _('Asset group list'),
+ 'assets': Asset.objects.all(),
+ 'system_users': SystemUser.objects.all(),
+ 'keyword': self.request.GET.get('keyword', '')
+ }
+ kwargs.update(context)
+ return super(AssetGroupListView, self).get_context_data(**kwargs)
+
+
+class AssetGroupDetailView(AdminUserRequiredMixin, DetailView):
+ model = AssetGroup
+ template_name = 'assets/asset_group_detail.html'
+ context_object_name = 'asset_group'
+
+ def get_context_data(self, **kwargs):
+ assets_remain = Asset.objects.exclude(id__in=self.object.assets.all())
+ system_users = self.object.system_users.all()
+ system_users_remain = SystemUser.objects.exclude(id__in=system_users)
+ context = {
+ 'app': _('Assets'),
+ 'action': _('Asset group detail'),
+ 'assets_remain': assets_remain,
+ 'assets': [asset for asset in Asset.objects.all()
+ if asset not in assets_remain],
+ 'system_users': system_users,
+ 'system_users_remain': system_users_remain,
+ }
+ kwargs.update(context)
+ return super(AssetGroupDetailView, self).get_context_data(**kwargs)
+
+
+class AssetGroupUpdateView(AdminUserRequiredMixin, UpdateView):
+ model = AssetGroup
+ form_class = forms.AssetGroupForm
+ template_name = 'assets/asset_group_create.html'
+ success_url = reverse_lazy('assets:asset-group-list')
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object(queryset=AssetGroup.objects.all())
+ return super(AssetGroupUpdateView, self).get(request, *args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ assets_all = self.object.assets.all()
+ context = {
+ 'app': _('Assets'),
+ 'action': _('Create asset group'),
+ 'assets_on_list': assets_all,
+ 'assets_count': len(assets_all),
+ 'group_id': self.object.id,
+ }
+ kwargs.update(context)
+ return super(AssetGroupUpdateView, self).get_context_data(**kwargs)
+
+
+class AssetGroupDeleteView(AdminUserRequiredMixin, DeleteView):
+ template_name = 'assets/delete_confirm.html'
+ model = AssetGroup
+ success_url = reverse_lazy('assets:asset-group-list')
diff --git a/apps/assets/views/idc.py b/apps/assets/views/idc.py
new file mode 100644
index 000000000..28dd92edc
--- /dev/null
+++ b/apps/assets/views/idc.py
@@ -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, 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')
diff --git a/apps/assets/views/system_user.py b/apps/assets/views/system_user.py
new file mode 100644
index 000000000..636dda8ac
--- /dev/null
+++ b/apps/assets/views/system_user.py
@@ -0,0 +1,139 @@
+# ~*~ coding: utf-8 ~*~
+
+from __future__ import absolute_import, unicode_literals
+from django.utils.translation import ugettext as _
+from django.conf import settings
+from django.db import transaction
+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.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 ..hands import AdminUserRequiredMixin
+
+__all__ = ['SystemUserCreateView', 'SystemUserUpdateView',
+ 'SystemUserDetailView', 'SystemUserDeleteView',
+ 'SystemUserAssetView', 'SystemUserListView',
+ ]
+
+
+class SystemUserListView(AdminUserRequiredMixin, TemplateView):
+ template_name = 'assets/system_user_list.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Assets'),
+ 'action': _('System user list'),
+ }
+ kwargs.update(context)
+ return super(SystemUserListView, self).get_context_data(**kwargs)
+
+
+class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
+ model = SystemUser
+ form_class = forms.SystemUserForm
+ template_name = 'assets/system_user_create.html'
+ success_url = reverse_lazy('assets:system-user-list')
+
+ @transaction.atomic
+ def post(self, request, *args, **kwargs):
+ return super(SystemUserCreateView, self).post(request, *args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Assets'),
+ 'action': _('Create system user'),
+ }
+ kwargs.update(context)
+ return super(SystemUserCreateView, self).get_context_data(**kwargs)
+
+ def form_invalid(self, form):
+ print(form.errors)
+ return super(SystemUserCreateView, self).form_invalid(form)
+
+ def get_success_message(self, cleaned_data):
+ success_message = _('Create system user %s successfully.' %
+ (
+ reverse_lazy('assets:system-user-detail', kwargs={'pk': self.object.pk}),
+ self.object.name,
+ ))
+
+ return success_message
+
+
+class SystemUserUpdateView(AdminUserRequiredMixin, UpdateView):
+ model = SystemUser
+ form_class = forms.SystemUserForm
+ template_name = 'assets/system_user_update.html'
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Assets'),
+ 'action': _('Update system user')
+ }
+ kwargs.update(context)
+ return super(SystemUserUpdateView, self).get_context_data(**kwargs)
+
+ def get_success_url(self):
+ success_url = reverse_lazy('assets:system-user-detail', kwargs={'pk': self.object.pk})
+ return success_url
+
+
+class SystemUserDetailView(AdminUserRequiredMixin, DetailView):
+ template_name = 'assets/system_user_detail.html'
+ context_object_name = 'system_user'
+ model = SystemUser
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Assets'),
+ 'action': _('System user detail')
+ }
+ kwargs.update(context)
+ return super(SystemUserDetailView, self).get_context_data(**kwargs)
+
+
+class SystemUserDeleteView(AdminUserRequiredMixin, DeleteView):
+ model = SystemUser
+ template_name = 'assets/delete_confirm.html'
+ success_url = reverse_lazy('assets:system-user-list')
+
+
+class SystemUserAssetView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
+ paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
+ template_name = 'assets/system_user_asset.html'
+ context_object_name = 'system_user'
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object(queryset=SystemUser.objects.all())
+ return super(SystemUserAssetView, self).get(request, *args, **kwargs)
+
+ def get_asset_groups(self):
+ return self.object.asset_groups.all()
+
+ # Todo: queryset default order by connectivity, need ops support
+ def get_queryset(self):
+ return list(self.object.get_assets())
+
+ def get_context_data(self, **kwargs):
+ asset_groups = self.get_asset_groups()
+ assets = self.get_queryset()
+ context = {
+ 'app': 'assets',
+ 'action': 'System user asset',
+ 'assets_remain': [asset for asset in Asset.objects.all() if asset not in assets],
+ 'asset_groups': asset_groups,
+ 'asset_groups_remain': [asset_group for asset_group in AssetGroup.objects.all()
+ if asset_group not in asset_groups]
+ }
+ kwargs.update(context)
+ return super(SystemUserAssetView, self).get_context_data(**kwargs)
+
+
+
+
+
+
diff --git a/apps/fixtures/init.json b/apps/fixtures/init.json
index 8707430c9..5b9a6a674 100644
--- a/apps/fixtures/init.json
+++ b/apps/fixtures/init.json
@@ -1 +1 @@
-[{"model": "users.usergroup", "pk": 1, "fields": {"is_discard": false, "discard_time": null, "name": "Default", "comment": "Default user group for all user", "date_created": "2016-11-25T06:50:28.410Z", "created_by": "System"}}, {"model": "assets.assetgroup", "pk": 1, "fields": {"name": "Default", "created_by": "", "date_created": "2016-11-25T06:50:28.627Z", "comment": "Default asset group", "system_users": []}}, {"model": "users.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$30000$RwSpXYAYQGbQ$PADpsQmM+cO5Y/R1CVSx3qNV4EbGIm2k+iMBXUtwvNc=", "last_login": null, "first_name": "", "last_name": "", "is_active": true, "date_joined": "2016-11-25T06:50:28.412Z", "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": "2086-11-08T06:50:28.412Z", "created_by": "System", "user_permissions": [], "groups": [1]}}]
\ No newline at end of file
+[{"model": "users.usergroup", "pk": 1, "fields": {"is_discard": false, "discard_time": null, "name": "Default", "comment": "Default user group", "date_created": "2017-04-04T01:59:21.128Z", "created_by": "System"}}, {"model": "assets.idc", "pk": 1, "fields": {"name": "Default", "bandwidth": "", "contact": "", "phone": "", "address": "", "intranet": "", "extranet": "", "date_created": "2017-04-04T01:59:21.140Z", "operator": "", "created_by": "System", "comment": "Default IDC"}}, {"model": "assets.assetgroup", "pk": 1, "fields": {"name": "Default", "created_by": "", "date_created": "2017-04-04T01:59:21.142Z", "comment": "Default asset group", "system_users": []}}, {"model": "users.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$30000$f8HLJLRwydBR$M+X1huSgQOojfaG01SGNBYPOlbYnHHw/A4/RdcSBEQQ=", "last_login": null, "first_name": "", "last_name": "", "is_active": true, "date_joined": "2017-04-04T01:59:20.932Z", "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-03-18T01:59:20.932Z", "created_by": "System", "user_permissions": [], "groups": [1]}}]
\ No newline at end of file
diff --git a/apps/users/models/__init__.py b/apps/users/models/__init__.py
index 9cdf1d61d..269f68bd4 100644
--- a/apps/users/models/__init__.py
+++ b/apps/users/models/__init__.py
@@ -5,3 +5,4 @@
from .group import *
from .user import *
from .authentication import *
+from .utils import *
diff --git a/apps/users/models/utils.py b/apps/users/models/utils.py
index 8a9b6c370..669e48f5a 100644
--- a/apps/users/models/utils.py
+++ b/apps/users/models/utils.py
@@ -5,7 +5,7 @@
from . import User, UserGroup
-def initial_model():
+def init_model():
for cls in [User, UserGroup]:
if getattr(cls, 'initial'):
cls.initial()
diff --git a/utils/export_init_data.sh b/utils/export_init_data.sh
index 4a9c90e6e..5786fa554 100644
--- a/utils/export_init_data.sh
+++ b/utils/export_init_data.sh
@@ -3,10 +3,13 @@
python2.7 ../apps/manage.py shell << EOF
from users.models import *
-init_all_models()
+init_model()
from assets.models import *
-init_all_models()
+init_model()
+
+from audits.models import LoginLog
+LoginLog.objects.all().delete()
EOF