• OpenStack虚拟机virtaulinterfance 网络设备在libvirt的代码梳理


    nova创建虚机网卡实际设备的代码调用流程为

    _create_domain_and_network---->plug_vifs-->LibvirtGenericVIFDriver.plug-----> plug_ovs_hybrid--->_plug_bridge_with_port。

    virtualinterface使用的dirver,由vif_driver参数决定,默认值为vif_driver=nova.virt.libvirt.vif.LibvirtGenericVIFDriver

    D:code-program官网nova-ocata
    ovavirtlibvirtvif.py
        def plug_ovs_hybrid(self, instance, vif):
            """Plug using hybrid strategy
    
            Create a per-VIF linux bridge, then link that bridge to the OVS
            integration bridge via a veth device, setting up the other end
            of the veth device just like a normal OVS port.  Then boot the
            VIF on the linux bridge using standard libvirt mechanisms.
    	创建一个per-VIF linux网桥,然后通过一个veth设备将该网桥链接到OVS集成网桥,
    	将veth设备的另一端设置为正常的OVS端口。
    	然后使用标准libvirt机制在linux桥上引导VIF
            """
            self._plug_bridge_with_port(instance, vif, port='ovs')	
    
    
        def _plug_bridge_with_port(self, instance, vif, port):
            iface_id = self.get_ovs_interfaceid(vif)
    	# 获取br_name, 以qbr开头
            br_name = self.get_br_name(vif['id'])
    	# 获取veth_pair_name, 以qvb,qvo开头
            v1_name, v2_name = self.get_veth_pair_names(vif['id'])
    	#v1_name是qvb,v2_name是qvo
    	# 添加一个 qbr 网桥
            if not linux_net.device_exists(br_name):
                utils.execute('brctl', 'addbr', br_name, run_as_root=True)
                utils.execute('brctl', 'setfd', br_name, 0, run_as_root=True)
                utils.execute('brctl', 'stp', br_name, 'off', run_as_root=True)
                utils.execute('tee',
                              ('/sys/class/net/%s/bridge/multicast_snooping' %
                               br_name),
                              process_input='0',
                              run_as_root=True,
                              check_exit_code=[0, 1])
                disv6 = '/proc/sys/net/ipv6/conf/%s/disable_ipv6' % br_name
                if os.path.exists(disv6):
                    utils.execute('tee',
                                  disv6,
                                  process_input='1',
                                  run_as_root=True,
                                  check_exit_code=[0, 1])
    
    	# 创建添加一个 qvo设备
            if not linux_net.device_exists(v2_name):
                mtu = vif['network'].get_meta('mtu')
    	    #v1_name是qvb,v2_name是qvo
    	    # 将两个veth创建为一个peer-port
                linux_net._create_veth_pair(v1_name, v2_name, mtu)-----s1创建peer-port设备
                utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True)
    	   # 将qvb接口添加到qbr上
                utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True)
                if port == 'ovs':
    	    # 将接口qvo桥接到br-int上
    	    # 分别传入的参数为:br-int, qvo, port['id'], port的mac地址, instance-uuid
                    linux_net.create_ovs_vif_port(self.get_bridge_name(vif),------s2 将qvo桥接到br-int上
                                                  v2_name, iface_id,
                                                  vif['address'], instance.uuid,
                                                  mtu)
                elif port == 'ivs':
                    linux_net.create_ivs_vif_port(v2_name, iface_id,
                                                  vif['address'], instance.uuid)
    s1创建peer-port设备
    def _create_veth_pair(dev1_name, dev2_name, mtu=None):
        """Create a pair of veth devices with the specified names,
        deleting any previous devices with those names.
        """
        for dev in [dev1_name, dev2_name]:
            delete_net_dev(dev)
    
        utils.execute('ip', 'link', 'add', dev1_name, 'type', 'veth', 'peer',
                      'name', dev2_name, run_as_root=True)
        for dev in [dev1_name, dev2_name]:
            utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True)
            utils.execute('ip', 'link', 'set', dev, 'promisc', 'on',
                          run_as_root=True)
            _set_device_mtu(dev, mtu)
    											  
    s2 将qvo桥接到br-int上
    def _create_ovs_vif_cmd(bridge, dev, iface_id, mac,
                            instance_id, interface_type=None):
        # 将接口qvo桥接到br-int上
        # 分别传入的参数为:br-int, qvo, port['id'], port的mac地址, instance-uuid
        cmd = ['--', '--if-exists', 'del-port', dev, '--',
                'add-port', bridge, dev,
                '--', 'set', 'Interface', dev,
                'external-ids:iface-id=%s' % iface_id,
                'external-ids:iface-status=active',
                'external-ids:attached-mac=%s' % mac,
                'external-ids:vm-uuid=%s' % instance_id]
        if interface_type:
            cmd += ['type=%s' % interface_type]
        return cmd
    
    
    def create_ovs_vif_port(bridge, dev, iface_id, mac, instance_id,
                            mtu=None, interface_type=None):
        _ovs_vsctl(_create_ovs_vif_cmd(bridge, dev, iface_id,
                                       mac, instance_id,
                                       interface_type))
        # Note at present there is no support for setting the
        # mtu for vhost-user type ports.
        if interface_type != network_model.OVS_VHOSTUSER_INTERFACE_TYPE:
            _set_device_mtu(dev, mtu)
        else:
            LOG.debug("MTU not set on %(interface_name)s interface "
                      "of type %(interface_type)s.",
                      {'interface_name': dev,
                       'interface_type': interface_type})
    

    由代码可以看出,至此,<qbr>--(qvb)--(qvo)--<br-int>就已经连接上了,至于虚机是如何与<qbr>连上的,这个就是在virt内部做的了,执行以下的命令, 其中的source字段是你提供的qbr, tap则是virt生成的.

    [root@test ~]# virsh domiflist 33
    Interface Type Source Model MAC
    -------------------------------------------------------
    tap437153df-04 bridge qbr437153df-04 virtio fa:16:3e:e6:99:cd  

    从代码中可以了解到,Nova创建虚拟机时,网络设备的创建,本质上,执行,brctl,ovs-vsctl及ip link的命令行

  • 相关阅读:
    C# 串口通信总结
    配置文件的读写
    配置文件入门
    锁机制与原子操作 <第四篇>
    线程池 异步I/O线程 <第三篇>
    线程池之ThreadPool类与辅助线程
    这一篇sigmoid和softmax的比较,讲的不错
    今天看到的关于深度学习的一篇文章,可以好好学习下
    git各种命令 & git merge和git rebase的区别
    ORA-19815,ORA-19809 :limit exceeded for recovery files
  • 原文地址:https://www.cnblogs.com/potato-chip/p/13183104.html
Copyright © 2020-2023  润新知