15.服务器资源2,create拆封

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__"  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值