【IMU_Ops】------IV------ IMU自动化运维平台之CMDB(添加新资产)

说明
本文中所有内容仅作为学习使用,请勿用于任何商业用途。
本文为原创,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明。

  上一章节,我们仅仅是做到在admin管理后台看见我们定义的所有models信息。本章节开始主要是实现CMDB中资产新增、新资产上线、资产更新、资产展示等功能。

 #A 新增资产

  首先需要更新视图文件view.py,先不要着急去撸代码,要搞清楚新增资产的大体逻辑再去撸代码(避免返工)下图为新增资产的逻辑图示及概述:

  •   其中assets-data应该是通过POST发送至服务端的资产原始数据;
  •   资产数据通过json转换为json数据类型;
  •   进行接收到的数据进行合理检查(安全性、合理性、完整性等);
  •   判断数据是否为空,若为空则返回错误信息并退出视图;
  •   判断数据是否为字典类型(这里为了方便操作,定义资产数据为字典类型),若非字典则返回错误信息并退出视图;
  •   判断数据是否带有SN,若非则返回错误信息并退出视图(SN是标示一个合法资产的唯一字段,不能缺少不能为空);

  下面我们根据以上逻辑,编写新增资产的视图代码:

 1 from django.shortcuts import HttpResponse
 2 from django.views.decorators.csrf import csrf_exempt
 3 import json
 4 from assets import models
 5 from assets import assets_handler
 6 
 7 
 8 # Create your views here.
 9 @csrf_exempt  #这里为了方便暂且跳过Django的csrf安全机制(后期再完善安全相关配置)
10 def report(request):
11     if request.method == "POST":
12         assets_data = request.POST.get('assets_data')
13         print(assets_data)
14         data = json.loads(assets_data)
15         # 判断data是否为空
16         if not data:
17             return HttpResponse("提交的数据为空!")
18         if not issubclass(dict, type(data)):
19             return HttpResponse("提交的数据必须是字典格式!")
20         # 判断提交的数据是否有唯一键:sn
21         sn = data.get('sn', None)
22         if sn:
23             # 判断是否为线上资产中存在的资产
24             assets_obj = models.Assets.objects.filter(sn=sn)
25             if assets_obj:
26                 # 更新线上资产信息
27                 update_assets = assets_handler.UpdateAsset(request, assets_obj[0], data)
28                 return HttpResponse("资产已更新!")
29             else:
30                 # 进入待审批区域
31                 obj = assets_handler.NewAssets(request, data)
32                 response = obj.add_to_new_assets_zone()
33                 return HttpResponse(response)
34         else:
35             return HttpResponse("提交的数据中未包含SN,请校验数据!")
36     return HttpResponse("怎么就200了!")
view.py

 #B 资产数据处理

  接下来,针对assets_data进行数据处理,在view文件中我们仅仅是针对数据进行了SN的判断和数据是否为空的判断。资产更新及提交资产到待审批区域还未解决,但这里我们还有几点需要明确的:

  通过SN在已上线的资产进行查找,若存在则进入已上线资产的更新流程;

  如果没有,说明这是个新资产,需要添加到新资产区;

  创建一个assets_handler.py文件,其中新建四个类分别实现四个功能:

  NewAssets(将资源新增到待审批区域)

  ApproveAssets(审批待上线的资源)

  UpdateAssets(更新已上线资产信息)

  Log(记录资产操作日志)

  整个数据处理的大体流程为:创建一个asset_handler.NewAsset()对象,然后调用它的obj.add_to_new_assets_zone()方法,将资产数据保存至models中的NewAssetsApprovalZone中(需要在models文件新增待审批区所需要的字段,models中代码会一并整理到第二章节中),根据实际情况,接收返回相应的结果;审批待上线资产则比较粗暴,一键审批并将待上线数据直接转正即可(从待审批区域移至资产表中);更新资产则是通过view中针对SN的判断来执行相应的数据更新即可。

  新增资产分两种情况:

  1.   彻底的新资产,任何区域都不存在该资产,直接添加至待审批区域即可;
  2.   已上线资产中没有该资产,但是待审批区中存在该资产(审批人还未审批的资产),此时再次接收到相同SN的资产时,只需要更新待审批区域该资产的数据即可;

  下面是assets_handler中各个功能模块的代码:

 

NewAssets
  1 class ApproveAssets:
  2     # 审批待上线资产
  3     def __init__(self, request, assets_id):
  4         self.request = request
  5         self.new_assets = models.NewAssetApprovalZone.objects.get(id=assets_id)
  6         self.data = json.loads(self.new_assets.data)
  7 
  8     def assets_online(self):
  9         # 预留接口
 10         func = getattr(self, "_%s_online" % self.new_assets.assets_type)
 11         ret = func()
 12         return ret
 13 
 14     def _server_online(self):
 15         assets = self._create_assets()
 16         try:
 17             self._create_manufacturer(assets)  # 创建厂商
 18             self._create_server(assets)  # 创建服务器
 19             self._create_cpu(assets)  # 创建CPU
 20             self._create_ram(assets)  # 创建内存
 21             self._create_disk(assets)  # 创建硬盘
 22             self._create_nic(assets)  # 创建网卡
 23             self._delete_original_asset()  # 从待审批资产区删除已审批上线的资产
 24         except Exception as e:
 25             assets.delete()
 26             log('approve_failed', msg=e, new_assets=self.new_assets, request=self.request)
 27             print(e)
 28             return False
 29         else:
 30             # 添加日志
 31             log("online", assets=assets, request=self.request)
 32             print("新服务器上线!")
 33             return True
 34 
 35     def _create_assets(self):
 36         # 创建资产并上线
 37         assets = models.Assets.objects.create(assets_type=self.new_assets.assets_type,
 38                                               assets_name="%s:%s" % (self.new_assets.assets_type, self.new_assets.sn),
 39                                               sn=self.new_assets.sn, assets_approved=self.request.user,)
 40         return assets
 41 
 42     def _create_manufacturer(self, asset):
 43         # 创建厂商
 44         m = self.new_assets.manufacturer
 45         if m:
 46             manufacturer_obj, _ = models.ManufacturerAssets.objects.get_or_create(name=m)
 47             asset.manufacturer = manufacturer_obj
 48             asset.save()
 49 
 50     def _create_server(self, asset):
 51         # 创建服务器
 52         models.ServerAssets.objects.create(assets=asset, model=self.new_assets.model, os_type=self.new_assets.os_type,
 53                                            os_distribution=self.new_assets.os_distribution,
 54                                            os_release=self.new_assets.os_release)
 55 
 56     def _create_cpu(self, asset):
 57         # 创建CPU
 58         cpu = models.CPUAssets.objects.create(assets=asset)
 59         cpu.cpu_model = self.new_assets.cpu_model
 60         cpu.cpu_count = self.new_assets.cpu_count
 61         cpu.cpu_core_count = self.new_assets.cpu_core_count
 62         cpu.save()
 63 
 64     def _create_ram(self, asset):
 65         # 创建内存
 66         ram_list = self.data.get('ram')
 67         if not ram_list:
 68             return
 69         for ram_dict in ram_list:
 70             if not ram_dict.get('slot'):
 71                 raise ValueError("内存插槽位置不存在!")
 72             ram = models.RAMAssets()
 73             ram.assets = asset
 74             ram.slot = ram_dict.get('slot')
 75             ram.sn = ram_dict.get('sn')
 76             ram.model = ram_dict.get('model')
 77             ram.manufacturer = ram_dict.get('manufacturer')
 78             ram.volume = ram_dict.get('volume', 0)
 79             ram.save()
 80 
 81     def _create_disk(self, asset):
 82         # 创建硬盘
 83         disk_list = self.data.get('physical_disk_driver')
 84         if not disk_list:  # 一条硬盘数据都没有
 85             return
 86         for disk_dict in disk_list:
 87             if not disk_dict.get('sn'):
 88                 raise ValueError("未知sn的硬盘!")  # 根据sn确定具体某块硬盘。
 89             disk = models.DiskAssets()
 90             disk.assets = asset
 91             disk.sn = disk_dict.get('sn')
 92             disk.model = disk_dict.get('model')
 93             disk.brand = disk_dict.get('brand'),
 94             disk.slot = disk_dict.get('slot')
 95             disk.volume = disk_dict.get('volume', 0)
 96             iface = disk_dict.get('interface_type')
 97             if iface in ['SATA', 'SAS', 'SCSI', 'SSD', 'unknown']:
 98                 disk.interface_type = iface
 99 
100             disk.save()
101 
102     def _create_nic(self, asset):
103         # 创建网卡
104         nic_list = self.data.get("nic")
105         if not nic_list:
106             return
107 
108         for nic_dict in nic_list:
109             if not nic_dict.get('mac'):
110                 raise ValueError("网卡缺少mac地址!")
111             if not nic_dict.get('model'):
112                 raise ValueError("网卡型号未知!")
113 
114             nic = models.NICAssets()
115             nic.assets = asset
116             nic.name = nic_dict.get('name')
117             nic.model = nic_dict.get('model')
118             nic.mac = nic_dict.get('mac')
119             nic.ip_address = nic_dict.get('ip_address')
120             if nic_dict.get('net_mask'):
121                 if len(nic_dict.get('net_mask')) > 0:
122                     nic.net_mask = nic_dict.get('net_mask')[0]
123             nic.save()
124 
125     def _delete_original_asset(self):
126         # 对审批通过的资产进行待审批区删除(其实不删除而是通过某个字段改变状态更合理,后期再优化吧)
127         self.new_assets.delete()
ApproveAssets
  1 class UpdateAsset:
  2     # 更新已上线资产信息
  3     def __init__(self, request, assets, report_data):
  4         self.request = request
  5         self.assets = assets
  6         self.report_data = report_data
  7         self.asset_update()
  8 
  9     def asset_update(self):
 10         # 预留接口
 11         func = getattr(self, "_%s_update" % self.report_data['assets_type'])
 12         ret = func()
 13         return ret
 14 
 15     def _server_update(self):
 16         try:
 17             self._update_manufacturer()  # 更新厂商
 18             self._update_server()  # 更新服务器
 19             self._update_cpu()  # 更新CPU
 20             self._update_ram()  # 更新内存
 21             self._update_disk()  # 更新硬盘
 22             self._update_nic()  # 更新网卡
 23             self.assets.save()
 24         except Exception as e:
 25             log('update_failed', msg=e, assets=self.assets, request=self.request)
 26             print(e)
 27             return False
 28         else:
 29             # 添加日志
 30             log("update_success", assets=self.assets)
 31             print("资产数据被更新!")
 32             return True
 33 
 34     def _update_manufacturer(self):
 35         # 更新厂商
 36 
 37         m = self.report_data.get('manufacturer')
 38         if m:
 39             manufacturer_obj, _ = models.ManufacturerAssets.objects.get_or_create(name=m)
 40             self.assets.manufacturer = manufacturer_obj
 41         else:
 42             self.assets.manufacturer = None
 43         self.assets.manufacturer.save()
 44 
 45     def _update_server(self):
 46         # 更新服务器
 47         self.assets.serverassets.model = self.report_data.get('model')
 48         self.assets.serverassets.os_type = self.report_data.get('os_type')
 49         self.assets.serverassets.os_distribution = self.report_data.get('os_distribution')
 50         self.assets.serverassets.os_release = self.report_data.get('os_release')
 51         self.assets.serverassets.save()
 52 
 53     def _update_cpu(self):
 54         # 更新CPU信息
 55         self.assets.cpu_assets .cpu_model = self.report_data.get('cpu_model')
 56         self.assets.cpu_assets.cpu_count = self.report_data.get('cpu_count')
 57         self.assets.cpu_assets.cpu_core_count = self.report_data.get('cpu_core_count')
 58         self.assets.cpu_assets.save()
 59 
 60     def _update_ram(self):
 61         """
 62         更新内存信息。
 63         使用集合数据类型中差的概念,处理不同的情况。
 64         如果新数据有,但原数据没有,则新增;
 65         如果新数据没有,但原数据有,则删除原来多余的部分;
 66         如果新的和原数据都有,则更新。
 67         在原则上,下面的代码应该写成一个复用的函数,
 68         但是由于内存、硬盘、网卡在某些方面的差别,导致很难提取出重用的代码。
 69         :return:
 70         """
 71         # 获取已有内存信息,并转成字典格式
 72         old_rams = models.RAMAssets.objects.filter(assets=self.assets)
 73         old_rams_dict = dict()
 74         if old_rams:
 75             for ram in old_rams:
 76                 old_rams_dict[ram.slot] = ram
 77         # 获取新数据中的内存信息,并转成字典格式
 78         new_rams_list = self.report_data['ram']
 79         new_rams_dict = dict()
 80         if new_rams_list:
 81             for item in new_rams_list:
 82                 new_rams_dict[item['slot']] = item
 83 
 84         # 利用set类型的差集功能,获得需要删除的内存数据对象
 85         need_deleted_keys = set(old_rams_dict.keys()) - set(new_rams_dict.keys())
 86         if need_deleted_keys:
 87             for key in need_deleted_keys:
 88                 old_rams_dict[key].delete()
 89 
 90         # 需要新增或更新的
 91         if new_rams_dict:
 92             for key in new_rams_dict:
 93                 defaults = {
 94                     'sn': new_rams_dict[key].get('sn'),
 95                     'model': new_rams_dict[key].get('model'),
 96                     'brand': new_rams_dict[key].get('brand'),
 97                     'volume': new_rams_dict[key].get('volume', 0),
 98                 }
 99                 models.RAMAssets.objects.update_or_create(assets=self.assets, slot=key, defaults=defaults)
100 
101     def _update_disk(self):
102         """
103         更新硬盘信息,类似更新内存。
104         """
105         old_disks = models.DiskAssets.objects.filter(assets=self.assets)
106         old_disks_dict = dict()
107         if old_disks:
108             for disk in old_disks:
109                 old_disks_dict[disk.sn] = disk
110 
111         new_disks_list = self.report_data['physical_disk_driver']
112         new_disks_dict = dict()
113         if new_disks_list:
114             for item in new_disks_list:
115                 new_disks_dict[item['sn']] = item
116 
117         # 需要删除的
118         need_deleted_keys = set(old_disks_dict.keys()) - set(new_disks_dict.keys())
119         if need_deleted_keys:
120             for key in need_deleted_keys:
121                 old_disks_dict[key].delete()
122 
123         # 需要新增或更新的
124         if new_disks_dict:
125             for key in new_disks_dict:
126                 interface_type = new_disks_dict[key].get('interface_type', 'unknown')
127                 if interface_type not in ['SATA', 'SAS', 'SCSI', 'SSD', 'unknown']:
128                     interface_type = 'unknown'
129                 defaults = {
130                     'slot': new_disks_dict[key].get('slot'),
131                     'model': new_disks_dict[key].get('model'),
132                     'brand': new_disks_dict[key].get('brand'),
133                     'volume': new_disks_dict[key].get('volume', 0),
134                     'interface_type': interface_type,
135                 }
136                 models.DiskAssets.objects.update_or_create(assets=self.assets, sn=key, defaults=defaults)
137 
138     def _update_nic(self):
139         """
140         更新网卡信息,类似更新内存。
141         """
142         old_nics = models.NICAssets.objects.filter(assets=self.assets)
143         old_nics_dict = dict()
144         if old_nics:
145             for nic in old_nics:
146                 old_nics_dict[nic.model + nic.mac] = nic
147 
148         new_nics_list = self.report_data['nic']
149         new_nics_dict = dict()
150         if new_nics_list:
151             for item in new_nics_list:
152                 new_nics_dict[item['model'] + item['mac']] = item
153 
154         # 需要删除的
155         need_deleted_keys = set(old_nics_dict.keys()) - set(new_nics_dict.keys())
156         if need_deleted_keys:
157             for key in need_deleted_keys:
158                 old_nics_dict[key].delete()
159 
160         # 需要新增或更新的
161         if new_nics_dict:
162             for key in new_nics_dict:
163                 if new_nics_dict[key].get('net_mask') and len(new_nics_dict[key].get('net_mask')) > 0:
164                     net_mask = new_nics_dict[key].get('net_mask')[0]
165                 else:
166                     net_mask = ""
167                 defaults = {
168                     'name': new_nics_dict[key].get('name'),
169                     'ip_address': new_nics_dict[key].get('ip_address'),
170                     'net_mask': net_mask,
171                 }
172                 models.NICAssets.objects.update_or_create(assets=self.assets, model=new_nics_dict[key]['model'],
173                                                           mac=new_nics_dict[key]['mac'], defaults=defaults)
174 
175         print('更新成功!')
UpdateAssets
 1 def log(log_type, msg=None, assets=None, new_assets=None, request=None):
 2     # 记录日志
 3     event = models.EventLog()
 4     if log_type == "online":
 5         event.name = "%s <%s> :  上线" % (assets.assets_name, assets.sn)
 6         event.assets = assets
 7         event.detail = "资产成功上线!"
 8         event.user = request.user
 9     elif log_type == "approve_failed":
10         event.name = "%s <%s> :  审批失败" % (new_assets.assets_type, new_assets.sn)
11         event.new_assets = new_assets
12         event.detail = "审批失败!
%s" % msg
13         event.user = request.user
14     elif log_type == "update_success":
15         event.name = "%s [%s] <%s> :  数据更新!" % (assets.assets_type, assets.assets_name, assets.sn)
16         event.assets = assets
17         event.detail = "更新成功!"
18     elif log_type == "update_failed":
19         event.name = "%s [%s] <%s> :  更新失败" % (assets.assets_type, assets.assets_name, assets.sn)
20         event.assets = assets
21         event.detail = "更新失败!
%s" % msg
22         # 更多日志类型.....
23     event.save()
Log

 #C 资产数据处理

  最后还有几个工作需要完成,我们有个view但是还缺少url的配置,还需要一些测试数据来检测我们的各个功能是否ok。

  首先我们完成rul的配置,为保证整个项目的代码可读性及高扩展性,我们更新IMU_DevOps目录下的urls文件:

1 from django.contrib import admin
2 from django.urls import path, include
3 
4 urlpatterns = [
5     path('admin/', admin.site.urls),
6     path('assets/', include('assets.urls'))
7 ]
urls.py

嗯时间到,需要带娃去跨年,今年就写到这里吧。明年再更新!在这里祝大家新年快乐!2020各种顺!

  接下来在assets包中新增urls.py这个文件并编写代码,主要是指定之前我们编写的view视图中的report方法。

1 from django.urls import path
2 from assets import views
3 
4 
5 app_name = 'assets'
6 
7 urlpatterns = [
8     path('report/', views.report, name='report')
9 ]
assets-urls.py

  然后我们分别新建Conf,Log的python package,其中Conf中主要用来存放和该项目相关的配置文件,工程目录中的settings文件我们仅针对整个工程做基础的设置,而每个模块的配置我们都单独来写,这样不仅修改某个配置文件的时候不会影响到整个工程,同时整个工程的扩展性也会大大提升。在Log包目录下新建一个IMU_assets.log文件(暂时用来存放测试log,正式log还是通过assets_handler.py中的log方法将其存放在数据库中),接下来撸代码:

 1 import os
 2 
 3 # 远端接收数据的服务器
 4 Params = {
 5     "server": "127.0.0.1",
 6     "port": 8000,
 7     'url': '/assets/report/',
 8     'request_timeout': 30,
 9 }
10 
11 # 日志文件配置
12 
13 PATH = os.path.join(os.path.dirname(os.getcwd()), 'Log', 'IMU_assets.log')
14 print(PATH)
Conf-assets_setting.py

  最后我们需要测试以上功能是否达到我们的需求,由于是测试我这边就临时写一个test的文件,在其中定义两台服务器的信息并将它发送至我们设置的服务端。

  1 import json
  2 import time
  3 import urllib.request
  4 import urllib.parse
  5 import os
  6 import sys
  7 from Conf import assets_setting
  8 
  9 BASE_DIR = os.path.dirname(os.getcwd())
 10 # 设置工作目录,使得包和模块能够正常导入
 11 sys.path.append(BASE_DIR)
 12 
 13 def update_test(data):
 14     """
 15     创建测试用例
 16     """
 17     # 将数据打包到一个字典内,并转换为json格式
 18     data = {"assets_data": json.dumps(data)}
 19     # print(data) 测试是否收到data
 20     # 根据assets_setting.py中的配置,构造url
 21     url = "http://%s:%s%s" % (assets_setting.Params['server'], assets_setting.Params['port'],
 22                               assets_setting.Params['url'])
 23     print('正在将数据发送至: [%s]  ......' % url + '100%')
 24     data_encode = urllib.parse.urlencode(data).encode()
 25     response = urllib.request.urlopen(url=url, data=data_encode, timeout=assets_setting.Params['request_timeout'])
 26     print("33[31;1m发送完毕!33[0m ")
 27     message = response.read().decode()
 28     print("返回结果:%s" % message)
 29     try:
 30         # 使用Python内置的urllib.request库,发送post请求。
 31         # 需要先将数据进行封装,并转换成bytes类型
 32         data_encode = urllib.parse.urlencode(data).encode()
 33         response = urllib.request.urlopen(url=url, data=data_encode, timeout=assets_setting.Params['request_timeout'])
 34         print("33[31;1m发送完毕!33[0m ")
 35         message = response.read().decode()
 36         print("返回结果:%s" % message)
 37     except Exception as e:
 38         message = "发送失败"
 39         print("33[31;1m发送失败,%s33[0m" % e)
 40 
 41     # 记录日志
 42     with open(assets_setting.PATH, 'ab') as f:
 43         log = '发送时间: %s 	 服务器地址: %s 	 返回结果:%s 
' % (time.strftime('%Y-%m-%d %H-%M-%S'), url, message)
 44         f.write(log.encode())
 45         print('日志已记录完成!')
 46 
 47 
 48 if __name__ == '__main__':
 49     windows_data = {
 50         "os_type": "Windows",
 51         "os_release": "2019 64bit ",
 52         "os_distribution": "Microsoft",
 53         "assets_type": "server",
 54         "cpu_count": 16,
 55         "cpu_model": "Intel(R) Core(TM) i9-9750H CPU @ 4.30GHz",
 56         "cpu_core_count": 64,
 57         "ram": [
 58             {
 59                 "slot": "A0",
 60                 "volume": 64,
 61                 "model": "Physical Memory",
 62                 "brand": "kingstone ",
 63                 "sn": "323126"
 64             },
 65             {
 66                 "slot": "A1",
 67                 "volume": 64,
 68                 "model": "Physical Memory",
 69                 "brand": "kingstone ",
 70                 "sn": "312136"
 71             },
 72 
 73         ],
 74         "manufacturer": "Dell inc.",
 75         "model": "Y9320K 2019",
 76         "wake_up_type": 3,
 77         "sn": "31233-OEM-1312-132we6",
 78         "physical_disk_driver": [
 79             {
 80                 "interface_type": "unknown",
 81                 "slot": 0,
 82                 "sn": "3456733121124566544",
 83                 "model": "SAMSUNG SV122164G ATA Device",
 84                 "brand": "希捷",
 85                 "volume": 2048
 86             },
 87             {
 88                 "interface_type": "SATA",
 89                 "slot": 1,
 90                 "sn": "312334332122365423",
 91                 "model": "Seagate SV1324264G ATA Device",
 92                 "brand": "希捷",
 93                 "volume": 2048
 94             },
 95 
 96         ],
 97         "nic": [
 98             {
 99                 "mac": "14:CF:22:EF:36:23",
100                 "model": "[00000066] Realtek RTL8192CU Wireless LAN 802.11n USB 2.0 Network Adapter",
101                 "name": 14,
102                 "ip_address": "10.8.8.17",
103                 "net_mask": [
104                     "255.255.255.0",
105                     "64"
106                 ]
107             },
108             {
109                 "mac": "0A:01:33:33:66:17",
110                 "model": "[00000336] VmWare WorkStation Host-Only Ethernet Adapter",
111                 "name": 24,
112                 "ip_address": "192.168.56.17",
113                 "net_mask": [
114                     "255.255.255.0",
115                     "64"
116                 ]
117             },
118             {
119                 "mac": "14:CF:22:FF:66:17",
120                 "model": "Intel Adapter",
121                 "name": 13,
122                 "ip_address": "192.1.1.17",
123                 "net_mask": ""
124             },
125 
126 
127         ]
128     }
129 
130     linux_data = {
131         "assets_type": "server",
132         "manufacturer": "IBM.",
133         "sn": "F3LN112",
134         "model": "K1 Power S930",
135         "uuid": "3334523-1266-4d12-804e-c6c2wwe66",
136         "wake_up_type": "Power Switch",
137         "os_distribution": "Ubuntu",
138         "os_release": "Ubuntu 16.04.4 LTS",
139         "os_type": "Linux",
140         "cpu_count": "16",
141         "cpu_core_count": "64",
142         "cpu_model": "POWER 9E",
143         "ram": [
144             {
145                 "slot": "RAM slot #0",
146                 "volume": 256,
147                 "model": "Physical Memory",
148                 "brand": "IBM",
149                 "sn": "616612"
150             }
151         ],
152         "size": 63.53899332970703,
153         "nic": [],
154         "physical_disk_driver": [
155             {
156                 "model": "ST2245LM035-1RK016",
157                 "volume": "2048",
158                     "sn": "WL23W26",
159                 "brand": "SanSung",
160                 "interface_type": "SATA"
161             }
162         ]
163     }
164 
165     update_test(linux_data)
166     update_test(windows_data)
assets_test.py

 #D 验证功能模块

  现在我们来测试以上功能是否能达到我们预期效果,主要步骤分以下几方面:

  1、由于更改过models.py文件,第一步先运行Python  manage.py makemigrations以及python manage.py migrate

2、运行assets_test.py

  从上图我们可以看出测试数据成功识别到setting中的服务端地址,并将数据成功发送至服务端,同时还记录的测试日志。

3、在admin后台查看待审批区域是否有我们刚提交的资产:

4、通过复选框选中两台待上线资产并进行审批通过,观察是否能顺利审核通过:

  接下来点击执行按钮

  在资产总表中查看是否能看见刚审核通过的资产:

5、修改assets_test.py中内容,我们将SN不做修改,其他信息做部分调整(windows服务器内存调整为128G/槽位;linux服务器包括SN都做部分修改),查看更新功能是否正常:

  首先查看IMU的工程debug信息:  

  接着查看windows服务器内存是否被更新,目前还没有详细资产展示,所以只能去内存资产管理中查看:

  由于linux我们修改了SN号,所以被认为是新资产,故直接进入待审批区域,这里我们直接审批就不截图了。最后看看总资产:2台linux服务器,1台windows服务器

6、查看日志是否正常记录(测试日志在工程目录中,系统日志在数据库的Log表中)

  其中有几条日志显示审批失败,后来找见原因是我的测试数据中内存槽位号重复了导致的。资产的新增、审批、更新就到这吧,下一章节开始弄前端,将整个资产进行一个统一的展示。

原文地址:https://www.cnblogs.com/4geek/p/12125474.html