分享

Neutron如何与Nova-Compute进行交互

sstutu 发表于 2015-3-16 21:57:06 [显示全部楼层] 只看大图 回帖奖励 阅读模式 关闭右栏 1 46864

问题导读

1.libvirt如何响应并创建相应的网卡设备?
2.Nova-compute如何发出请求?






开门见山,最近在研究了一下Neutton的代码,看的过程中也将所了解的内容进行整理,整理内容如下:
Nova-compute如何发出请求
当我执行nova boot的时候,nova-compute是如何执行接下来的操作呢,贴个代码说起来也太罗嗦了,还是直接用一个流程图来说明一下,然后再根据他图来说明一下就比较直观吧
不过看图容易画图难啊,为了表示函数调用层级,我用数字放在方法前面,比如0 methodA -> 1 methodB -> 2 methodC -> 0 methodD. 就表明,methodA里面调用了methodB,methodB里面调用了methodC,然后methodA结束了,开始调用methodD.OK,上图:
1.png
Openstack毕竟是各个不同的模块组合起来的,上面的流程是通用的, 不管你是用neutron-ovs,nova-network,neutron-ml2,还是libvirt,lxc,hyperv等, 不变的部分它就长这样了.
既然通用的都说完了,那么接下来就到了如何去管理和创建网络资源了.这里我们就采用Neutron-OVS和libvirt来为例说明.
图中其中两个标红的操作,一个post_message_to_create_and_bind和plug,就是接下来要说明的重点:Neutron-OVS返回port并绑定,libvirt如何响应并创建相应的网卡设备
Neutron-OVS返回port并绑定
  1. # OVSNeutronPluginV2下的create_port,Neutron-server最后会调用这个方法
  2. def create_port(self, context, port):
  3.     port['port']['status'] = q_const.PORT_STATUS_DOWN
  4.     port_data = port['port']
  5.     session = context.session
  6.     with session.begin(subtransactions=True):
  7.         self._ensure_default_security_group_on_port(context, port)
  8.         sgids = self._get_security_groups_on_port(context, port)
  9.         dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, [])
  10.         # 创建port
  11.         port = super(OVSNeutronPluginV2, self).create_port(context, port)
  12.         # 绑定port和host, 实际上是执行插入portbindingports表
  13.         self._process_portbindings_create_and_update(context, port_data, port)
  14.         # 绑定port和security, 实际上是执行插入securitygroupportbindings表
  15.         # 作用嘛,肯定就是用来执行port的securitygroup的操作啦
  16.         self._process_port_create_security_group(context, port, sgids)
  17.         # 执行插入extradhcpopts
  18.         # TODO? 这个作用我还不清楚
  19.         self._process_port_create_extra_dhcp_opts(context, port,
  20.                                                     dhcp_opts)
  21.         # 配置db,以允许该机器与外界进行通信,以后会生成iptables
  22.         # http://blog.csdn.net/matt_mao/article/details/19417451
  23.         port[addr_pair.ADDRESS_PAIRS] = (
  24.             self._process_create_allowed_address_pairs(
  25.                 context, port,
  26.                 port_data.get(addr_pair.ADDRESS_PAIRS)))
  27.     # 通知相关的agent执行security_group的更新,通常就是iptables
  28.     self.notify_security_groups_member_updated(context, port)
  29.     return port
复制代码


另外,由于OVSNeutronPluginV2的init方法中,存在base_binding_dict这么一个属性
  1. class OVSNeutronPluginV2(...):
  2.    def __init__(self, configfile=None):
  3.         self.base_binding_dict = {
  4.             portbindings.VIF_TYPE: portbindings.VIF_TYPE_OVS,
  5.             portbindings.CAPABILITIES: {
  6.                 portbindings.CAP_PORT_FILTER:
  7.                 'security-group' in self.supported_extension_aliases}}
复制代码


在代码中可以看到,其初始化为base_binding_dict['binding:vif_type']='ovs', 在之后的一些代码中会被update到port中.这个执行neutron port-show中可以看到对应的值,同时,在最后的libvirt的plug方法中也是起着判断因素的.
libvirt如何响应并创建相应的网卡设备
这里就直接上代码,逻辑也不是很复杂.
2.png
跟下plug的代码就知道了,其实根据配置文件来选择哪一个vif_driver的.在旧版的代码中,你还是有很多选择的,但是在新版的代码里面就只有LibvirtGenericVIFDriver

  1. # 如此的配置在旧版的nova是可行的,不过代码中会有提示说已经废弃了,建议使用GenericVIFDriver
  2. libvirt_vif_driver = nova.virt.libvirt.vif.LibvirtHybridOVSBridgeDriver
  3. # 所以还是使用如下的配置
  4. libvirt_vif_driver = nova.virt.libvirt.vif.LibvirtGenericVIFDriver
复制代码
此处就以OVS的创建代码来说明了

  1. def plug_ovs_hybrid(self,instance,vif):
  2.     iface_id = self.get_ovs_interfaceid(vif)
  3.     # 获取了br_name, 以qbr开头
  4.     br_name = self.get_br_name(vif['id'])
  5.     # 获取了veth_pair_name, 以qvb,qvo开头
  6.     v1_name,v2_name = self.get_veth_pair_names(vif['id'])
  7.     # 添加一个qbr 网桥
  8.     if not linux_net.device_exists(br_name):
  9.         utils.execute('brctl','addbr',br_name,run_as_root=True)
  10.         utils.execute('brctl','setfd',br_name,0,run_as_root=True)
  11.         utils.execute('brctl','stp',br_name,'off',run_as_root=True)
  12.         utils.execute('tee',
  13.                       ('/sys/class/net/%s/bridge/multicast_snooping' %
  14.                        br_name),
  15.                       process_input='0',
  16.                       run_as_root=True,
  17.                       check_exit_code=[0,1])
  18.     # 创建添加一个qvo网桥
  19.     if not linux_net.device_exists(v2_name):
  20.         # 将两个veth创建为一个peer-port
  21.         linux_net._create_veth_pair(v1_name,v2_name)
  22.         utils.execute('ip','link','set',br_name,'up',run_as_root=True)
  23.         # 将qvb接口添加到qbr上
  24.         utils.execute('brctl','addif',br_name,v1_name,run_as_root=True)
  25.         # 将接口qvo桥接到br-int上
  26.         # 分别传入的参数为:br-int, qvo, port['id'], port的mac地址, instance-uuid
  27.         linux_net.create_ovs_vif_port(self.get_bridge_name(vif),
  28.                                       v2_name,iface_id,vif['address'],
  29.                                       instance['uuid'])
  30. def _create_veth_pair(dev1_name, dev2_name):
  31.     # 将两个veth创建为一个peer-port
  32.     for dev in [dev1_name, dev2_name]:
  33.         delete_net_dev(dev)
  34.     utils.execute('ip', 'link', 'add', dev1_name, 'type', 'veth', 'peer',
  35.                   'name', dev2_name, run_as_root=True)
  36.     for dev in [dev1_name, dev2_name]:
  37.         utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True)
  38.         utils.execute('ip', 'link', 'set', dev, 'promisc', 'on',
  39.                       run_as_root=True)
  40. def create_ovs_vif_port(bridge, dev, iface_id, mac, instance_id):
  41.     # 将接口qvo桥接到br-int上
  42.     # 分别传入的参数为:br-int, qvo, port['id'], port的mac地址, instance-uuid
  43.     utils.execute('ovs-vsctl', '--', '--may-exist', 'add-port',
  44.                   bridge, dev,
  45.                   '--', 'set', 'Interface', dev,
  46.                   'external-ids:iface-id=%s' % iface_id,
  47.                   'external-ids:iface-status=active',
  48.                   'external-ids:attached-mac=%s' % mac,
  49.                   'external-ids:vm-uuid=%s' % instance_id,
  50.                   run_as_root=True)
复制代码
由代码可以看出,至此,<qbr>--(qvb)--(qvo)--<br-int>就已经连接上了 至于虚机是如何与<qbr>连上的,这个就是在virt内部做的了,执行以下的命令, 其中的source字段是你提供的qbr, tap则是virt生成的.
  1. virsh domiflist
复制代码
到这里可以看出,从一个nova-compute到neutron到libvrit的各个网络信息的处理交互. 逻辑相对来说还是比较清晰的。
终于整理完了之后,感觉变成了nova-compute的源码分析了。。。








欢迎加入about云群425860289432264021 ,云计算爱好者群,关注about云腾讯认证空间

已有(1)人评论

跳转到指定楼层
chistpest 发表于 2015-11-23 13:00:54
谢谢搂住,学习了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条