from rest_framework import serializers
from servers.models import Server,NetworkDevice,IP
from manufacturer.models import ProductModel,Manufacturer
class ServerAutoReportSerializer(serializers.Serializer):
"""
服务器同步序列化,这相当于是第一步检查,在这一步不做外键检查。
manufacturer = serializers.PrimaryKeyRelatedField(many=False,queryset=Manufacturer.objects.all())
"""
ip = serializers.IPAddressField(required=True)
hostname = serializers.CharField(required=True, max_length=20)
cpu = serializers.CharField(required=True, max_length=50)
mem = serializers.CharField(required=True, max_length=20)
disk = serializers.CharField(required=True, max_length=200)
os = serializers.CharField(required=True, max_length=50)
sn = serializers.CharField(required=True, max_length=50)
manufacturer = serializers.CharField(required=True)
model_name = serializers.CharField(required=True)
uuid = serializers.CharField(required=True, max_length=50)
#网卡和ip模型,server表中没有这个,它是一个关联对象
network = serializers.JSONField(required=True)
''''
一、先处理制造商,因为它自身没有任何关联关系,两种情况
1.它存在,只需要拿到它,返回供应商的instance
2.不存在,则需要创建,单独定义方法创建它
总之,这个validate_manufacturer方法,在返回的时候一定要有 Manufacturer实例
'''
def validate_manufacturer(self, value):
try:
return Manufacturer.objects.get(vendor_name__exact=value)
# 如果Manufacturer则创建它
except Manufacturer.DoesNotExist:
return self.create_manufacturer(value)
def create_manufacturer(self,vendor_name):
return Manufacturer.objects.create(vendor_name=vendor_name)
'''
二、服务器型号
验证完制造商后,处理服务器型号,它只能在对象(表)级别验证的时候操作。
首先拿到制造商的instacne,因为型号和制造商是多对一关系。
这个attr存储的是server的所有数据,是个键值对。manufacturer_obj = attrs['manufacturer'] 它可以得到对应制造商的instance
拿到一个制造商的对象后,需要检查有没有这个型号。如果制造商没有这个型号,则创建
如果何种情况,一定要将这个型号转换成对应型号的实例,然后返回
'''
def validate(self, attrs):
# network = attrs["network"]
# del attrs["network"] # 在处理字段的时候,处理完成要删除它,后续create保存的时候,会检查字段是否匹配
manufacturer_obj = attrs['manufacturer']
try:
# 在制造商实例对应的产品模型中查找是否有这个型号的模型
attrs['model_name'] = manufacturer_obj.productmodel_set.get(model_name__exact=attrs['model_name'])
#在供应商下面的产品型号中查找是否有这个型号。如果存在返回,不存在报异常,就会去创建。它需要提供制造商的实例。
except ProductModel.DoesNotExist:
# 如果没有就创建这个模型,包含模型名称和制造商
attrs['model_name'] = self.create_product_model(manufacturer_obj, attrs["model_name"])
return attrs
# 验证完成后,就可以创建模型
def create_product_model(self,manufacturer_obj,model_name):
return ProductModel.objects.create(model_name=model_name,vendor_name=manufacturer_obj)
'''
额外知识:
字典 pop() 方法删除字典给定键 key 及对应的值,返回值为被删除的值。key 值必须给出。 否则,返回 default 值。
site= {'name': '菜鸟教程', 'alexa': 10000, 'url': 'www.runoob.com'}
pop_obj=site.pop('name')
print pop_obj # 输出 :菜鸟教程
'''
'''
三、生成server
字段级别验证和对象(表)基表验证完成后。因为是post提交,所以是create
因为当前这张表没有network这个字段。所以插入数据到表的时候,需要先将这个字段拿出来(也从原有的字典中剔除)。 再生成服务器的instance。
注意:网卡的检查,需要先有servers的实例,才能检查。因为它和服务器的关系是n:1,是有关联关系的。
'''
'''
def create(self,validated_data):
# pop就是删掉network,对字典的操作.返回值就是个被删除的值. 因为Server没有这个字段,所以需要剔除处理
# 移除数据库模型中不存在的属性
network= validated_data.pop("network")
# 内部调用django模型类的save()方法
server_obj = Server.objects.create(**validated_data) # 创建server 记录
#server_obj.networkdevice_set = network_queryset # 设置它当中的一个集合等于列表。做一对多的关系
# 需要先做判断,再关联。 因为网卡里有
self.check_server_network_device(server_obj,network)
return validated_data
'''
'''
四、处理网卡
'''
def check_server_network_device(self, server_obj, network):
'''
# 当前服务器所有网卡
这个网卡设备是否存在,它需要根据服务器来进行判断。
先拿到当前服务器所有网卡,然后一条一条处理。来比对网卡设备表当中是否有当前服务器的网卡。
如果不存在,则创建。 创建的时候需要注意它必须要关联上是哪台服务器。所以必须要提供server的instance
'''
'''
如果删除或更新了网卡,则应该将关联的 IP 一并删除
拿到当前网卡和之前网卡。 做差集。进行删除(之前有的网卡,现在没有的网卡),并且会删掉这个网卡对应的所有IP地址
'''
# 处理之前的网卡设备
network_device_queryset = server_obj.networkdevice_set.all()
# 保存当前的网卡设备
current_network_device_queryset=[]
for device in network:
try:
# 检测device是否存在,如果不存在抛出异常
network_device_obj=network_device_queryset.get(name__exact=device['name'])
except NetworkDevice.DoesNotExist:
# device不存在
network_device_obj=self.create_network_device(server_obj, device)
current_network_device_queryset.append(network_device_obj)
for network_device_obj in list(set(network_device_queryset)-set(current_network_device_queryset)):
network_device_obj.delete()
def create_network_device(self, server_obj, device):
# 网卡设备当中没有ip字段,需要pop,device才能保存
ips = device.pop('ips')
# 这个device[“host”] 这个host是个外键,需要指定server的instance。
device['host'] = server_obj
# 创建设备
device_device_obj = NetworkDevice.objects.create(**device)
# 继续处理网卡对应的IP
self.check_ip(device_device_obj, ips)
return device_device_obj
'''
五、处理IP
接下来处理IP
检查IP的时候,必须要知道这个IP是在哪块网卡设备上。
检查ip是根据这个IP是在哪块网卡上。
先拿到所有网卡上的所有IP,进行匹配。如果存在不做任何操作。
如果不存在,则创建这些IP 到对应网卡上。
'''
def check_ip(self, network_device_obj, ifnets):
# 处理之前的ip
ip_queryset= network_device_obj.ip_set.all()
# 当前的IP
current_ip_queryset = []
# 这个ifnet是当前所有网卡的IP
for ifnet in ifnets:
try:
# 如果不存在则创建
ip_obj=ip_queryset.get(ip_addr__exact=ifnet['ip_addr'])
except IP.DoesNotExist:
ip_obj=self.create_ip(network_device_obj, ifnet)
current_ip_queryset.append(ip_obj)
# 处理之前的IP和当前IP的差集。目的是删掉 在旧的当中并且不在新的当中的IP。
for ip_obj in list(set(ip_queryset)-set(current_ip_queryset)):
ip_obj.delete()
# 创建这些IP 到对应网卡上。
def create_ip(self, network_device_obj, ifnet):
ifnet['device'] = network_device_obj
return IP.objects.create(**ifnet)
'''
第三步的create,做个拆分,如果post的对象包含相同的uuid(虚拟机) 或者sn(物理机)则是更新
否则就是创建。
'''
# 验证服务器
def create(self, validated_data):
print("create")
sn = validated_data['sn']
uuid = validated_data['uuid']
try:
# 检测是否存在
## 虚拟机uuid
## 物理机sn
if sn == uuid or sn == "" or sn.startswith('vmware'):
#虚拟机
server_obj = Server.objects.get(uuid__contains=uuid)
else:
#物理机
server_obj = Server.objects.get(sn__contains=sn)
except Server.DoesNotExist:
# 不存在,则创建
return self.create_server(validated_data)
else:
# 存在则,更新
return self.update_server(server_obj, validated_data)
# 入口的create通过判断 如果不存在 create_server,如果存在就是update_server
def create_server(self, validated_data):
print('create')
network = validated_data.pop('network')
server_obj = Server.objects.create(**validated_data)
self.check_server_network_device(server_obj, network)
return validated_data
# 创建 post 更新是put。所以需要判断,第一次是post,后面是put
def update_server(self, instance, validated_data):
print('update')
instance.ip = validated_data.get("ip", instance.ip)
instance.hostname = validated_data.get("hostname", instance.hostname)
instance.cpu = validated_data.get("cpu", instance.cpu)
instance.mem = validated_data.get("mem", instance.mem)
instance.disk = validated_data.get("disk", instance.disk)
instance.os = validated_data.get("os", instance.os)
instance.save()
self.check_server_network_device(instance, validated_data['network'])
return instance
class ServerSerializer(serializers.ModelSerializer):
"""
服务器序列化类
"""
class Meta:
model=Server
fields="__all__"
class IPSerializer(serializers.ModelSerializer):
"""
服务器同步序列化类
"""
class Meta:
model=IP
fields="__all__"
class NetworkDeviceSerializer(serializers.ModelSerializer):
"""
服务器同步序列化类
"""
class Meta:
model=NetworkDevice
fields="__all__"
15.服务器资源2,create拆封
最新推荐文章于 2024-07-23 13:28:07 发布