diff --git a/apps/cmdb/forms.py b/apps/cmdb/forms.py index 0e62e9b..0511b0c 100644 --- a/apps/cmdb/forms.py +++ b/apps/cmdb/forms.py @@ -52,8 +52,6 @@ class DeviceCreateForm(forms.ModelForm): exclude = ['dev_connection'] error_messages = { 'hostname': {'required': '请填写设备地址'}, - 'buyDate': {'required': '请填写购买日期'}, - 'warrantyDate': {'required': '请填写到保日期'} } def clean(self): diff --git a/apps/cmdb/models.py b/apps/cmdb/models.py index bb516c5..a05aeee 100644 --- a/apps/cmdb/models.py +++ b/apps/cmdb/models.py @@ -92,12 +92,12 @@ class DeviceInfo(AbstractMode, DeviceAbstract, TimeAbstract): hostname = models.CharField(max_length=50, verbose_name='设备地址(IP或域名)') network_type = models.IntegerField(blank=True, null=True, verbose_name='网络类型') service_type = models.IntegerField(blank=True, null=True, verbose_name='服务类型') - operation_type = models.IntegerField(blank=True, null=True, verbose_name='业务类型') - leader = models.IntegerField(blank=True, null=True, verbose_name='责任人') + operation_type = models.IntegerField(blank=True, null=True, verbose_name='所属项目') + config = models.CharField(max_length=80, blank=True, default='', verbose_name='配置信息') dev_cabinet = models.IntegerField(blank=True, null=True, verbose_name='机柜信息') dev_connection = models.IntegerField(blank=True, null=True, verbose_name='连接信息') - buyDate = models.DateField(default=datetime.now, verbose_name="购买日期") - warrantyDate = models.DateField(default=datetime.now, verbose_name="到保日期") + buyDate = models.DateField(default=datetime.now, blank=True, null=True, verbose_name="购买日期") + warrantyDate = models.DateField(default=datetime.now, blank=True, null=True, verbose_name="到保日期") desc = models.TextField(blank=True, default='', verbose_name='备注信息') changed_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL) history = HistoricalRecords(excluded_fields=['add_time', 'modify_time', 'parent']) @@ -120,3 +120,59 @@ class DeviceFile(TimeAbstract): file_content = models.FileField(upload_to="asset_file/%Y/%m", null=True, blank=True, verbose_name="资产文件") upload_user = models.CharField(max_length=20, verbose_name="上传人") + +class Supplier(models.Model): + firm = models.CharField(max_length=200, verbose_name='供应商') + contact_details = models.CharField(max_length=200, verbose_name='联系信息') + desc = models.CharField(max_length=200, blank=True, default='', verbose_name='备注信息') + + class Meta: + verbose_name = '供应商管理' + verbose_name_plural = verbose_name + + +class NetworkAsset(models.Model): + name = models.CharField(max_length=100, verbose_name='资产名称') + ip_address = models.CharField(max_length=100, blank=True, default='', verbose_name='IP地址') + management = models.CharField(max_length=100, blank=True, default='', verbose_name='管理地址') + show_on_top = models.BooleanField(default=False, verbose_name='首页展示') + provider = models.ForeignKey('Supplier', blank=True, null=True, on_delete=models.SET_NULL, verbose_name='服务商') + desc = models.TextField(blank=True, default='', verbose_name='备注信息') + + class Meta: + verbose_name = '网络资产' + verbose_name_plural = verbose_name + + +class DomainName(AbstractMode): + dn_type_choices = (('1', '主域名'),('2', '二级域名')) + domain = models.CharField(max_length=200, verbose_name='域名') + dn_type = models.CharField(max_length=20, choices=dn_type_choices, default='1') + addr_resolution = models.ForeignKey('NatRule', blank=True, null=True, + on_delete=models.SET_NULL, verbose_name='解析地址') + resolution_server = models.ForeignKey('Supplier', related_name='res_server', + blank=True, null=True, on_delete=models.SET_NULL, verbose_name='解析服务') + domain_provider = models.ForeignKey('Supplier', related_name='do_provider', + blank=True, null=True, on_delete=models.SET_NULL, verbose_name='解析服务') + state = models.BooleanField(default=True, verbose_name='状态') + ssl = models.FileField(upload_to="ssl_file/%Y/%m", null=True, blank=True, verbose_name="SSL证书") + buyDate = models.DateField(default=datetime.now, blank=True, null=True, verbose_name='购买日期') + warrantyDate = models.DateField(default=datetime.now, blank=True, null=True, verbose_name='到保日期') + desc = models.TextField(blank=True, default='', verbose_name='备注信息') + + class Meta: + verbose_name = '域名管理' + verbose_name_plural = verbose_name + + +class NatRule(models.Model): + internet_ip = models.CharField(max_length=80, blank=True, default='', verbose_name='互联网IP') + src_port = models.IntegerField(blank=True, default='', verbose_name='源端口') + lan_ip = models.CharField(max_length=80, blank=True, default='', verbose_name='内网IP') + dest_port = models.IntegerField(blank=True, default='', verbose_name='目的端口') + state = models.BooleanField(default=True, verbose_name='状态') + desc = models.TextField(blank=True, default='', verbose_name='备注信息') + + class Meta: + verbose_name = 'NAT规则' + verbose_name_plural = verbose_name \ No newline at end of file diff --git a/apps/cmdb/templatetags/extra_tags.py b/apps/cmdb/templatetags/extra_tags.py index f4568c9..3bf24e8 100644 --- a/apps/cmdb/templatetags/extra_tags.py +++ b/apps/cmdb/templatetags/extra_tags.py @@ -27,8 +27,6 @@ def get_change_compare(changes): log = replace_log(key, value, Code, 'value') elif key == 'dev_cabinet': log = replace_log(key, value, Cabinet, 'number') - elif key == 'leader': - log = replace_log(key, value, User, 'name') else: log = '字段:"%(field)s",由:"%(old)s",变更为:"%(new)s"。' % { 'field': key, diff --git a/apps/cmdb/urls.py b/apps/cmdb/urls.py index 5856c99..0f1e35c 100644 --- a/apps/cmdb/urls.py +++ b/apps/cmdb/urls.py @@ -38,4 +38,10 @@ urlpatterns = [ path('eam/device/file_delete/', views_eam.DeviceFileDeleteView.as_view(), name='eam-device-file_delete'), path('eam/device/auto_update_device_info/', views_eam.AutoUpdateDeviceInfo.as_view(), name='eam-device-auto_update_device_info'), + + path('eam/supplier/', views_eam.SupplierView.as_view(), name='eam-supplier'), + path('eam/supplier/create/', views_eam.SupplierCreateView.as_view(), name='eam-supplier-create'), + path('eam/supplier/update/', views_eam.SupplierUpdateView.as_view(), name='eam-supplier-update'), + path('eam/supplier/list/', views_eam.SupplierListView.as_view(), name='eam-supplier-list'), + path('eam/supplier/delete/', views_eam.SupplierDeleteView.as_view(), name='eam-supplier-delete'), ] diff --git a/apps/cmdb/views_eam.py b/apps/cmdb/views_eam.py index 4264164..f0f76fd 100644 --- a/apps/cmdb/views_eam.py +++ b/apps/cmdb/views_eam.py @@ -10,7 +10,8 @@ from django.forms.models import model_to_dict from system.mixin import LoginRequiredMixin from custom import (BreadcrumbMixin, SandboxDeleteView, SandboxListView, SandboxUpdateView, SandboxCreateView) -from .models import Cabinet, DeviceInfo, Code, ConnectionInfo, DeviceFile +from .models import (Cabinet, DeviceInfo, Code, ConnectionInfo, DeviceFile, + Supplier) from .forms import DeviceCreateForm, DeviceUpdateForm, ConnectionInfoForm, DeviceFileUploadForm from utils.db_utils import MongodbDriver from utils.sandbox_utils import LoginExecution @@ -75,7 +76,7 @@ class DeviceView(LoginRequiredMixin, BreadcrumbMixin, TemplateView): class DeviceListView(SandboxListView): model = DeviceInfo - fields = ['id', 'sys_hostname', 'sn_number', 'os_type', 'device_type', 'hostname', 'mac_address', 'leader'] + fields = ['id', 'sys_hostname', 'hostname', 'service_type', 'operation_type', 'config', 'dev_cabinet', 'network_type'] def get_filters(self): data = self.request.GET @@ -90,18 +91,23 @@ class DeviceListView(SandboxListView): filters['service_type'] = data['service_type'] if 'operation_type' in data and data['operation_type']: filters['operation_type'] = data['operation_type'] + if 'dev_cabinet' in data and data['dev_cabinet']: + filters['dev_cabinet'] = data['dev_cabinet'] return filters def get_datatables_paginator(self, request): context_data = super().get_datatables_paginator(request) data = context_data['data'] for device in data: - user_id = device['leader'] - device['leader'] = get_object_or_404( - User, pk=int(user_id)).name if user_id else '' + service_type = device['service_type'] + operation_type = device['operation_type'] + dev_cabinet = device['dev_cabinet'] + network_type = device['network_type'] + device['operation_type'] = get_object_or_404(Code, pk=int(operation_type)).value if operation_type else '' + device['network_type'] = get_object_or_404(Code, pk=int(network_type)).value if network_type else '' + device['service_type'] = get_object_or_404(Code, pk=int(service_type)).value if service_type else '' + device['dev_cabinet'] = get_object_or_404(Cabinet, pk=int(dev_cabinet)).number if dev_cabinet else '' return context_data - - class DeviceCreateView(SandboxCreateView): model = DeviceInfo form_class = DeviceCreateForm @@ -233,3 +239,35 @@ class AutoUpdateDeviceInfo(LoginRequiredMixin, View): else: res['status'] = 'con_empty' return JsonResponse(res) + + +class SupplierView(LoginRequiredMixin, BreadcrumbMixin, TemplateView): + template_name = 'cmdb/supplier.html' + + +class SupplierCreateView(SandboxCreateView): + model = Supplier + fields = '__all__' + + +class SupplierUpdateView(SandboxUpdateView): + model = Supplier + fields = '__all__' + + +class SupplierListView(SandboxListView): + model = Supplier + fields = '__all__' + + def get_filters(self): + data = self.request.GET + filters = {} + if 'number' in data and data['number']: + filters['number__icontains'] = data['number'] + if 'position' in data and data['position']: + filters['position__icontains'] = data['position'] + return filters + + +class SupplierDeleteView(SandboxDeleteView): + model = Supplier \ No newline at end of file diff --git a/apps/system/views_user.py b/apps/system/views_user.py index 30274e2..879000e 100644 --- a/apps/system/views_user.py +++ b/apps/system/views_user.py @@ -25,7 +25,8 @@ User = get_user_model() class IndexView(LoginRequiredMixin, View): def get(self, request): - return render(request, 'index.html') + #return render(request, 'index.html') + return HttpResponseRedirect('/cmdb/') class LoginView(View): @@ -34,10 +35,10 @@ class LoginView(View): if not request.user.is_authenticated: return render(request, 'system/users/login.html') else: - return HttpResponseRedirect('/') + return HttpResponseRedirect('/cmdb/') def post(self, request): - redirect_to = request.GET.get('next', '/') + redirect_to = request.GET.get('next', '/cmdb/') login_form = LoginForm(request.POST) ret = dict(login_form=login_form) print(request.META.get('REMOTE_ADDR')) diff --git a/requirements/pro.txt b/requirements/pro.txt index b04e5cd..3c36817 100644 --- a/requirements/pro.txt +++ b/requirements/pro.txt @@ -5,10 +5,10 @@ ipython==7.1.1 pyyaml==4.2b1 ruamel.yaml==0.15.80 python-nmap==0.6.1 -redis==3.0.1 +redis==3.2.1 pymongo==3.7.1 paramiko==2.4.2 django-simple-history==2.6.0 celery==4.2.1 celery-once==2.0.0 -flower==0.9.2 +flower diff --git a/templates/base-static.html b/templates/base-static.html index 7e4b9a3..5795529 100644 --- a/templates/base-static.html +++ b/templates/base-static.html @@ -8,7 +8,7 @@ scratch. This page gets rid of all links and provides the needed markup only.
-