nova与neutron交互

1     nova命令

先介绍一下nova命令中与网络相关的一些参数。

1.1   指定网络启动虚机


usage: nova boot [--flavor <flavor>] [--image <image>]

[--image-with <key=value>] [--boot-volume <volume_id>]

[--snapshot <snapshot_id>] [--min-count <number>]

[--max-count <number>] [--meta <key=value>]

[--file <dst-path=src-path>] [--key-name <key-name>]

[--user-data <user-data>]

[--availability-zone <availability-zone>]

                 [--security-groups <security-groups>]

[--block-device-mapping <dev-name=mapping>]

[--block-device key1=value1[,key2=value2...]]

[--swap <swap_size>]

[--ephemeral size=<size>[,format=<format>]]

[--hint <key=value>]

[--nic <net-id=net-uuid,v4-fixed-ip=ip-addr,v6-fixed-ip=ip-addr,port-id=port-uuid>]

[--config-drive <value>] [--poll]

<name>

其中,v4/6-fixed-ip不能单独配置,必须和net-id一起配置;在一个--nic中net-id与port-id只能选择一个。

命令示例:


根据Port-ID启动虚机:

# neutron port-create  accd72eb-2cd0-4961-ad67-d028c92e5254  --fixed-ip ip_address=1.2.3.20

# nova boot --flavor 100 --image 18f8b6e1-a957-4d94-a3dd-eca757afdeb9  \

--nic port-id=10e7e093-156e-402b-9a45-ff8ab13dfb03 test_vm_1

启动虚机时指定网络,指定IP:

# nova boot --flavor 100 --image 18f8b6e1-a957-4d94-a3dd-eca757afdeb9 \

--nic net-id=accd72eb-2cd0-4961-ad67-d028c92e5254,v4-fixed-ip=1.2.3.10 test_vm_2

创建多网络虚机:

# nova boot --flavor 100 --image 18f8b6e1-a957-4d94-a3dd-eca757afdeb9 \

--nic net-id=accd72eb-2cd0-4961-ad67-d028c92e5254 \

--nic net-id= 2125e96e-d2a3-42b3-931f-5a90149d0f90 test_vm_3

1.2   修改虚机网络

nova支持对于active的虚机添加或删除网卡,对应命令如下:


interface-attach            Attach a network interface to a server.

interface-detach            Detach a network interface from a server.

interface-list              List interfaces attached to a server.

用法:

nova interface-attach [--port-id <port_id>] [--net-id <net_id>]

[--fixed-ip <fixed_ip>]

<server>

nova interface-detach <server> <port_id>

命令示例:


绑定一个端口、网络或者IP地址到虚机:

nova interface-attach 06fd79d1-99a8-451d-955c-f466b8986f34 --port-id c310babc-c833-4b10-9d76-78d60a58af98

将port-id从虚机解绑:

nova interface-detach 8dd2fb5d-30a9-45c7-8931-ba039adcd20f  5138a9ce-7114-4126-82e8-8685a6aeccee

查看虚机对应的Port端口:

[[email protected] ~]# nova interface-list   f09c0b84-8e5a-4a3d-8da9-7d57d105e0e3

+------------+--------------------------------------+--------------------------------------+--------------+-------------------+

| Port State | Port ID                              | Net ID                               | IP addresses | MAC Addr          |

+------------+--------------------------------------+--------------------------------------+--------------+-------------------+

| ACTIVE     | 182b1ed7-beab-46cd-84b1-1daf72f4e266 | accd72eb-2cd0-4961-ad67-d028c92e5254 | 1.2.3.12     | fa:16:3e:3f:3a:91 |

| ACTIVE     | 51b10239-005d-4d20-8d03-269bc85bacc6 | 2125e96e-d2a3-42b3-931f-5a90149d0f90 | 1.1.1.32     | fa:16:3e:d5:6c:5a |

+------------+--------------------------------------+--------------------------------------+--------------+-------------------+

2     nova介绍

2.1   Nova服务

nova主要服务包括:

nova-api:对外提供rest-api。

nova-conductor:用于分发消息。

nova-scheduler:在创建虚机时,选择计算节点。

nova-compute:在计算节点上运行,负责管理虚机的生命周期。

3     处理流程

3.1   创建虚机流程

用户创建虚机的命令到达nova-api后,通过rpc发给nova-conductor处理。conductor中,先通过nova-scheduler选择虚机调度到的主机,然后发送到对应主机的nova-compute上进行处理。

如下是nova-compute处理虚机创建的详细流程。

与网络相关的部分,简要地可以分为几部:

1)  创建网络资源,此时更新neutron port,或者创建neutron port,返回VIF列表

2)  libvirt spawn,根据VIF列表,配置虚机底层网络,然后起虚机进程,并等待虚机启动完成。

3)  ovs-agent捕获到虚机网卡添加到br-int中,发送rpc给plugin更新neutron db port状态为up。

4)  neutron db检测到端口up,发送network-vif-plug event通知nova端口。

l  日志分析

创建虚机,通过查看nova-computedebug日志,可以大致了解虚机启动过程。


allocate_for_instance /usr/lib/python2.7/site-packages/nova/network/neutronv2/api.py

GET http://controller:9696/v2.0/networks.json?id=2

GET http://controller:9696/v2.0/security-groups.json?tenant_id=

POST http://controller:9696/v2.0/ports.json

‘{"port": {"binding:host_id": "compute1", "admin_state_up": true, "network_id": "2337cce4-512c-4b36-a5a7-6af99bfe21d2", "tenant_id": "47227b9865f64869aee959af81caf8dd", "device_owner": "compute:nova", "security_groups": ["17be47bc-1629-4266-812f-a0750975f89f"], "device_id": "74f3bd67-4362-477d-b700-c10866dea8a6"}}‘

GET http://controller:9696/v2.0/ports.json?tenant_id=47227b9865f64869aee959af81caf8dd&device_id=74f3bd67-4362-477d-b700-c10866dea8a6

GET http://controller:9696/v2.0/floatingips.json?fixed_ip_address=1.1.1.4&port_id=2cbc7875-b460-4c59-b87f-078e1ff1d5b6

GET http://controller:9696/v2.0/subnets.json?id=dd0ea246-b2f8-498e-adce-c59eec7f8d91

GET http://controller:9696/v2.0/ports.json?network_id=2337cce4-512c-4b36-a5a7-6af99bfe21d2&device_owner=network%3Adhcp

sudo nova-rootwrap /etc/nova/rootwrap.conf brctl addbr qbr2cbc7875-b4

sudo nova-rootwrap /etc/nova/rootwrap.conf brctl setfd qbr2cbc7875-b4 0

sudo nova-rootwrap /etc/nova/rootwrap.conf brctl stp qbr2cbc7875-b4 off

sudo nova-rootwrap /etc/nova/rootwrap.conf tee /sys/class/net/qbr2cbc7875-b4/bridge/multicast_snooping

sudo nova-rootwrap /etc/nova/rootwrap.conf ip link add qvb2cbc7875-b4 type veth peer name qvo2cbc7875-b4

sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set qvb2cbc7875-b4 up

sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set qvb2cbc7875-b4 promisc on

sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set qvo2cbc7875-b4 up

sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set qvo2cbc7875-b4 promisc on

sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set qbr2cbc7875-b4 up

sudo nova-rootwrap /etc/nova/rootwrap.conf brctl addif qbr2cbc7875-b4 qvb2cbc7875-b4

sudo nova-rootwrap /etc/nova/rootwrap.conf ovs-vsctl --timeout=120 -- --if-exists del-port qvo2cbc7875-b4 -- add-port br-int qvo2cbc7875-b4 -- set Interface qvo2cbc7875-b4 external-ids:iface-id=2cbc7875-b460-4c59-b87f-078e1ff1d5b6 external-ids:iface-status=active external-ids:attached-mac=fa:16:3e:d9:e1:2f external-ids:vm-uuid=74f3bd67-4362-477d-b700-c10866dea8a6

Received event network-vif-plugged-2cbc7875-b460-4c59-b87f-078e1ff1d5b6 external_instance_event

代码分析如下:

l  nova-compute

1. conductor创建虚机的消息通过到达计算节点的nova-compute。

2. nova-compute创建虚机过程:

代码路径:ComputeManager.build_and_run_instance

通过spawn_n异步执行 _do_build_and_run_instance,这样rpcworker可以立即返回接着处理后面的消息了

_do_build_and_run_instance:

1)记录虚机状态为BUILDING

2)记录任务状态为SCHEDULING

3)如果conductor没有传入主机名,已当前主机作为创建资源的node。

4) _build_and_run_instance函数。见下面 _build_and_run_instance

5)捕获异常RescheduledException,如果配置了不retry,_cleanup_allocated_networks,然后结束。

6)捕获异常RescheduledException,如果配置了retry:

执行cleanup_instance_network_on_host,但这里实际并不会删除neutron port。

记录任务状态为SCHEDULING

本地调用conductor api重新build_instances。

7)捕获InstanceNotFound,UnexpectedDeletingTaskStateError,执行_cleanup_allocated_networks。

8)捕获BuildAbortException,执行_cleanup_allocated_networks。

9)其他异常,_cleanup_allocated_networks,_cleanup_volumes。

结束。

_build_and_run_instance 

1)_build_resources()创建各种资源,包括网络相关资源。

_build_networks_for_instance()配置网络,见_build_networks_for_instance

如果失败,报error log,Failed to allocate network(s)。结束。

2)调用driver.spawn创建实例。详见12 spawn.

3)报日志:Took %0.2f seconds to spawn the instance on ‘the hypervisor.

4)捕获异常:InstanceNotFound,ComputeResourcesUnavailable,报异常BuildAbortException

捕获异常:ComputeResourcesUnavailable,报异常:RescheduledException

捕获异常:BuildAbortException,

捕获异常FixedIpLimitExceeded,NoMoreNetworks,NoMoreFixedIps,报异常:BuildAbortException

捕获异常VirtualInterfaceCreateException,VirtualInterfaceMacAddressException,报异常BuildAbortException

捕获异常:FlavorDiskTooSmall,FlavorMemoryTooSmall,ImageNotActive,ImageUnacceptable,报异常:BuildAbortException

捕获其他异常:报异常RescheduledException。

5)删除实例的system_metadata, network_allocated

6)根据network_info分配IP地址。

7)_update_instance_after_spawn

更新虚机的状态为ACTIVE

8)_update_scheduler_instance_info

结束。

3. nova-compute build网络过程:

代码路径: ComputeManager._build_networks_for_instance

1)从instance的system_metadata中查看network_allocated属性,如果已经创建,说明虚机之前调度过,执行如下过程,然后结束。

· 在host上重新setup网络,setup_instance_network_on_host,参数:instance, host。见4 setup_instance_network_on_host.

· 获取并返回网络信息。

2)调用driver.macs_for_instance,生成mac地址。

libvirt driver不需要指定mac,ironic driver需要指定mac。

3)调用driver.dhcp_options_for_instance,生成dhcp_options。

libvirt driver不需要指定dhcp options。

4)更新实例的staus为NETWORKING,调用self._allocate_network分配网络资源。参考6
nova-compute 异步分配网络。

5)结束。

4. nova-compute setup_instance_network_on_host

代码路径: network.neutronv2.api.API._update_port_binding_for_instance()

1)通过neutronclient遍历Port,根据instance上的device_id和tenant_id过滤Port。

2)如果port的binding:host_id属性不是要配置的host,通过neutronclient的update_port方法更新端口信息。参考5. neutron update_port:

    3)结束。

6. nova-compute异步分配网络:

代码路径:nova/compute/manager.ComputeManager._allocate_network_async

1)调用driver.network_binding_host_id取得虚机所在的host信息。

2)调用network_api.allocate_for_instance,参照7。如果失败,进行重试。

关于重试:

a)配置文件中network_allocate_retries,指定了重试次数,默认为0,表示只创建1次,不重试。

b)重试间隔,1s,2s,4s,8,16,30,30...。

c)重试超过数目后,报异常,Instance failed network setup after %(attempts)d attempt(s)‘。

d)结束。

7. nova-compute 分配网络:

代码路径:nova/network/neutronv2/api.API.allocate_for_instance

1)如果neutronclient有port_binding_extension,使用neutronclient,否则使用admin的neutronclient。

2)检查实例是否有project_id,如果没有,报异常,empty project id for instance %s。结束。

3)根据传入的requested_networks、hypervisor_macs属性,调用_process_requested_networks函数

取得ports, net_ids, ordered_networks, available_macs。详见8.

4)调用_get_available_networks,通过neutronclient取得net_ids对应的network详情。

5)如果配置了requested_networks,但没有查询到networks,报NetworkNotFound异常。结束。

6)如果没有requested_networks,并且没有查询到networks,返回空的network。

7)检测虚机所附属的网络,如果是外部网络,必须是shared网络,否则报ExternalNetworkAttachForbidden异常,然后结束。

8)处理安全组,传入的安全组是安全组名称或者uuid列表。

通过neutronclient查询租户内的安全组。

如果有多个安全组有相同的名称,报NoUniqueMatch异常,Multiple security groups found matching  ‘%s‘. Use an ID to be more specific.

如果查询不到安全组,报SecurityGroupNotFound异常。

查询得到安全组ID列表。

9)遍历所有虚机附属的网络,

如果配置了安全组,并且网络没有配置子网,报SecurityGroupCannotBeApplied异常。

如果配置了安全组,并且port_security_enabled配置为False,报SecurityGroupCannotBeApplied异常。

10)port的device_id配置为instance.uuid,port的device_owner配置为compute:+instance.availability_zone,

port的binding:host_id配置为bind_host_id。

如果网络指定了port-id,通过neutronclient update_port

如果网络没指定port-id,调用self._create_port创建port,详见9

11)通过get_instance_nw_info获取网络信息,详见11。

12)返回网络列表。

13)结束。

8. nova-compute 处理已存在port-id:

代码路径:nova/network/neutronv2/api.API._process_requested_networks

1)遍历request 列表。request包含net-id, port-id

2)如果request中包含port-id:

通过neutronclient取得port详情。如果失败报异常,然后结束。

如果tenant_id不是实例的project_id,报PortNotUsable异常,然后结束。

如果port中包含device_id属性,报PortInUse异常,然后结束。

如果port的binding:vif_type属性为VIF_TYPE_BINDING_FAILED,报PortBindingFailed异常,然后结束。

如果指定了available_macs,port的mac_address值必须在available_macs中,否则报PortNotUsable异常,然后结束。

3)结束。

9. nova-compute创建port:

代码路径:nova/network/neutronv2/api.API._create_port

1)如果指定了fixed_ip,填上port[‘fixed_ips‘]属性。

2)填上network_id,admin_state_up,tenant_id属性。

3)如果指定了security_group_ids,填上security_groups属性。

4)如果指定了available_macs,如果available_macs为空,报PortNotFree异常。然后结束创建port。

否则弹出一个mac,填到port mac_address属性里。

5)如果指定了dhcp_opts,填上extra_dhcp_opts属性。

6)通过neutronclient调用create_port。详见10.

如果port的binding:vif_type属性为VIF_TYPE_BINDING_FAILED,调neutronclient删除端口,然后报PortBindingFailed异常。

如果neutron client报InvalidIpForNetworkClient异常,报InvalidInput异常,并且报error log,Neutron error: %(ip)s is not a valid IP address ‘

‘for network %(network_id)s.

如果neutron client报文IpAddressInUseClient异常,报FixedIpAlreadyInUse异常,并报error log,Neutron error: Fixed IP %s is ‘

‘already in use.

如果neutron client报OverQuotaClient异常,报PortLimitExceeded异常,并报error log,Neutron error: Port quota exceeded in tenant: %s

如果neutron client报IpAddressGenerationFailureClient异常,报NoMoreFixedIps异常,并报error log,Neutron error: No more fixed IPs in network: %s

如果neutron client报MacAddressInUseClient异常,报PortInUse异常,并报error log,Neutron error: MAC address %(mac)s is already ‘

‘in use on network %(network)s.

其他异常,保存并直接报一次,并且log,Neutron error creating port on network %s

7)结束。

11. nova-compute get_instance_nw_info:

代码路径:nova/network/api.API.get_instance_nw_info

1)调用_get_instance_nw_info,将nw_info写入db cache。

2)_build_network_info_model。

_build_network_info_model:

1)通过admin权限的neutron client,获取port列表,通过tenant_id和device_id过滤port。

2)返回的结果数据结构是network_model.NetworkInfo,是个list,成员是network_model.VIF.

3)network_model.VIF是个dict,对应虚机虚拟网卡的信息,

包括属性:id, address, type,details, devname, ovs_interfaceid, qbh_params, qbg_params,

active, vnic_type, profile, preserve_on_delete,meta,

这个VIF用于driver plug_vif。

12. driver.spawn:

代码路径:nova/virt/libvirt/driver.LibvirtDriver.spawn

1)查询disk_info信息。

2)_create_image。

3)查询xml _get_guest_xml

4)创建_create_domain_and_network。详见13.

5)等待instance的state为RUNNING

6)结束。

13. _create_domain_and_network

    代码路径:nova/virt/libvirt/driver.LibvertDriver._create_domain_and_network

1) 配置项:vif_plugging_timeout表示读取neutron发来的port_plugin_event消息的超时时间,默认300秒。

2)执行下面的操作,等待neutron发来的event消息。

3)plug_vifs,创建qvo/qbr/qvb,将qvo加入br-int。详见14。

4)setup_basic_filtering

5)prepare_instance_filter

6)apply_instance_filter

7)如果上面执行的动作超时,如果vif_plugging_is_fatal配置为True(默认为True,北基中配置为False),虚机创建失败,否则虚机可以创建成功。

14. plug_vifs

代码路径:nova/virt/libvirt/driver.LibvertDriver.plug_vifs

1) 遍历虚机网络的vif(即neutron port),执行libvirt_vif_driver的plug动作。

2)libvirt_vif_driver为:LibvirtGenericVIFDriver

3)根据vif_type选择不同的plug函数。对于ovs类型的vif_type:

4)如果端口binding:vif_details上配置了port_filter,并且使能了安全组,或者binding:vif_details中配置了ovs_hybrid_plug。调用plug_ovs_hybrid。

其他情况调用:plug_ovs_bridge,不做任何处理。

plug_ovs_hybrid:

1)如果qbr网桥不存在,

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])

2)如果qvo不存在,

linux_net._create_veth_pair(v1_name, v2_name)

utils.execute(‘ip‘, ‘link‘, ‘set‘, br_name, ‘up‘, run_as_root=True)

utils.execute(‘brctl‘, ‘addif‘, br_name, v1_name, run_as_root=True)

_ovs_vsctl([‘--‘, ‘--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])

如果使能了MTU配置,

utils.execute(‘ip‘, ‘link‘, ‘set‘, dev, ‘mtu‘,

mtu, run_as_root=True,

check_exit_code=[0, 2, 254])

l  neutron plugin

5. neutron update_port

Ml2Plugin继承db_base_plugin_v2.NeutronDbPluginV2,

NeutronDbPluginV2实现了update_port方法。

代码路径:

1)检查device_owner和device_id。

代码:_enforce_device_owner_not_router_intf_or_device_id

如果普通租户要修改owner或者device_id,如果owner修改为network:router_interface或者network:router_interface_distributed,

查询l3plugin中是否存在此router-id,如果存在,报异常,DeviceIDNotOwnedByTenant。

如果l3plugin不存在,也报异常,DeviceIDNotOwnedByTenant

2)检查mac地址:

代码:_check_mac_addr_update

如果修改mac字段,检测device_owner,如果以network:打头,不允许修改,报异常,UnsupportedPortDeviceOwner。

3)如果修改fixed_ip字段:

代码:_update_ips_for_port

检测是否超过max_fixed_ips_per_port,默认5个。如果超过,报异常,Exceeded maximim amount of fixed ips per port。

这里还有其他一些检查,报各种异常,不展开了。

存储已分配的IP:_store_ip_allocation

4)更新port,写入db:

port.update(xxx)

session.flush()

5) 结束。

10. neutron 创建port:

代码路径:neutron/plugins/ml2/plugin.ML2Plugin.create_port

1) _create_port_db 见下面

2) 发送events.AFTER_CREATE

3)调用mech_driver的create_port_postcommit

4)_set_default_qos,配置端口默认qos

5)如果port是dhcp或router,调security_groups_provider_updated

否则触发security_groups_member_updated,更新安全组成员。

6)_bind_port_if_needed,如果前面没有bind_port,这里会进行bind。

_create_port_db:

代码路径:neutron/plugins/ml2/plugin.ML2Plugin._create_port_db

1)db.create_port,见下面。

2)调extension.create_port

3) 如果配置了port-security,处理port-security。

4)调db.add_port_binding

5)_process_port_binding

6)处理allowed_address_pairs

7)处理extra_dhcp_opts

8)mech)driver.create_port_precommit

db.create_port:

代码路径:neutron/db/db_base_plugin_v2.NeutronDbPluginV2.create_port

1)如果port中没有id属性,通过uuidutils.generate_uuid生成一个uuid。

2)从port里,或者context里取tenant_id属性。如果两者不一致,报AdminRequired异常,Cannot create resource for another tenant。

3)如果配置了device_owner,检查device_owner和device_id。

代码:_enforce_device_owner_not_router_intf_or_device_id

如果普通租户要修改owner或者device_id,如果owner修改为network:router_interface或者network:router_interface_distributed,

查询l3plugin中是否存在此router-id,如果存在,报异常,DeviceIDNotOwnedByTenant。

如果l3plugin不存在,也报异常,DeviceIDNotOwnedByTenant

4)调用get_network,确保网络存在。

5)如果mac不存在,调用_generate_mac生成mac。如果出错,按照配置文件中mac_generation_retries可以多试几次。

如果mac生成失败,报MacAddressGenerationFailure异常,并且报error 日志,Unable to generate mac address after %s attempts。

6)通过mac往neutron db中写port,如果db报DBDuplicateEntry异常,报MacAddressInUse异常。

7)结束。

3.2   删除虚机流程

删除虚机相对于创建虚机比较简单,不重点分析了。

1. nova/compute/manager.py ComputeManager

terminate_instance,

_delete_instance

1) clear_events_for_instance

2) 置虚机状态delete.start

3) _shutdown_instance

4) instance.info_cache.delete()

5) _cleanup_volumes

6) 置虚机状态vm_states.DELETED

7) instance.destroy() 删除db

8) _complete_deletion,

恢复quota, 删除block device mappings

如果使能了vnc,清楚vnc授权key

通知scheduler删除虚机调度信息

2 _shutdown_instance

1) 从cache中取得network_info,如果没有cache,空的network_info

2) 读取block_device_info,

3) 调libvirt driver.destroy.

4) _try_deallocate_network,删除在neutron中创建的nova port。

5)删除volume。

3 driver.destroy.

_destroy

1) virt_dom.destroy()删除虚机qemu进程

cleanup

1) _unplug_vifs

2) unfilter_instance删除安全组规则

3) 删除磁盘文件。

4. unplug_vifs

1)只有binding:vif_details   | {"port_filter": true, "ovs_hybrid_plug": true}才会删除port。

2)执行命令:‘brctl‘, ‘delif‘, br_name, v1_name, 将qvb从qbr中删除

3) 执行命令‘ip‘, ‘link‘, ‘set‘, br_name, ‘down‘,将qbr down掉

4)执行命令:‘brctl‘, ‘delbr‘, br_name,   删除qbr

5)执行命令:_ovs_vsctl([‘--‘, ‘--if-exists‘, ‘del-port‘, bridge, dev]),从br-int中删除qvo

6)执行命令:‘ip‘, ‘link‘, ‘delete‘, dev,删除qbo

3.3    port-binding

nova-compute创建虚机时通过update-port,更新了device_id和device_owner和binding:host_id属性。

ml2plugin在收到update_port或者create_port时,会进行port-binding,填写port的binding:profile,binding:vif_details,binding:vif_type,和binding:vnic_type属性。

比如


+-----------------------+---------------------------------------------------------------------------------+

| Field                 | Value                                                                           |

+-----------------------+---------------------------------------------------------------------------------+

| admin_state_up        | True                                                                            |

| allowed_address_pairs |                                                                                 |

| binding:host_id       | node-84                                                                         |

| binding:profile       | {}                                                                              |

| binding:vif_details   | {"port_filter": true, "ovs_hybrid_plug": true}                                  |

| binding:vif_type      | ovs                                                                             |

| binding:vnic_type     | normal                                                                          |

| device_id             | 5aa2ccff-2a91-4256-afb6-d8cd0505a106                                            |

| device_owner          | compute:nova                                                                    |

| extra_dhcp_opts       |                                                                                 |

| fixed_ips             | {"subnet_id": "e4ec7c6b-117f-467f-adb3-33c280e4ccb3", "ip_address": "1.1.1.13"} |

| id                    | 43d61251-d85f-4358-a1cf-fbba6484c011                                            |

| mac_address           | fa:16:3e:06:9e:62                                                               |

| name                  |                                                                                 |

| network_id            | 2125e96e-d2a3-42b3-931f-5a90149d0f90                                            |

| security_groups       | e2325d15-6e49-4720-9496-3c73d362293b                                            |

| status                | ACTIVE                                                                          |

| tenant_id             | 0baf9c928cdc4192babdf869e0cee498                                                |

我们可能会遇到binding:vif_type为binding_failed的现象,一般这种情况出现在部署阶段,原因是配置错误

这里列举几个常见binding_failed的原因:

1. agent配置中没有配置tenant_type。

2. 创建vlan/flat网络时指定physical_network,但是配置文件中没有。

3. 创建的网络类型在所有的ovs-agent配置文件中都没有定义。

3.4   nova-compute中的数据结构

在查看代码时,经常可以看到网络相关变量,如果不知道数据结构代码比较难理解。

nova中网络相关的数据结构定义在:nova/network/model.py中。

主要的model:networkInfo,VIF, Network

networkInfo是基于list派生出的类,其成员是VIF。

VIF是基于dict派生出的类,描述的是虚机的一个虚拟网卡的信息。

VIF属性主要包括:id,address,network,type,details,devname,ovs_interfaceid,active,                     vnic_type,profile。

其中:

network是Network model。

ovs_interfaceid,在vif_type是ovs时,为port-uuid,vif_type是其他时,为空。

devname为tap+port uuid,截取14字符。

Network model描述了虚机网卡对应的网络信息。

主要属性包括:id,bridge,label,tenant_id ,subnets。

其中id是网络id,bridge是绑定的网桥,比如br-int,label是网络名称,

4     附录

4.1   虚机端口恢复脚本

我们可能会遇到虚机是存在的,但底层qvb/qvo/qbr配置不正确的现象,这有可能是虚机创建或迁移过程中出现的,在k版代码中,重启nova-compute可会恢复qvb/qbr/qvo的配置。

但在I版中,或者在上线业务中,不能随意重启nova-compute,此时我们需要手动恢复端口。

脚本内容如下:


#cat yanxingan/gen_nova_cfg_by_ip.sh

#!/bin/bash

if [ $# == 0 ]; then

echo "usage: gen_nova_cfg_by_ip <VM-IP>";

exit;

fi

echo VM-IP is: $1

source /root/openrc

echo

echo Retrieve port-id from neutron db. Please wait...

portid=`neutron port-list |grep $1 | awk -F ‘|‘ ‘{print $2}‘ |sed ‘s/^[ \t]*//g‘ | sed ‘s/[ \t]*$//g‘  `

echo port-id is: ${portid}

if [ -z $portid ]; then

echo "Fail to ecec neutron port-list. Please retry.";

exit;

fi

echo

echo Retrieve port info by id from neutron db. Please wait...

portinfo=`neutron port-show $portid |grep -E ‘(binding:host_id|mac_address|device_id)‘ |sed ‘s/^[ \t]*//g‘ | sed ‘s/[ \t]*$//g‘ `

host=`echo -e $portinfo |awk -F ‘|‘ ‘{print $3}‘ |sed ‘s/^[ \t]*//g‘ | sed ‘s/[ \t]*$//g‘`

device=`echo -e $portinfo |awk -F ‘|‘ ‘{print $6}‘ |sed ‘s/^[ \t]*//g‘ | sed ‘s/[ \t]*$//g‘ `

mac=`echo -e $portinfo |awk -F ‘|‘ ‘{print $9}‘ |sed ‘s/^[ \t]*//g‘ | sed ‘s/[ \t]*$//g‘`

echo host is: $host

echo vm-id is: $device

echo mac is: $mac

echo

sleep 1s

echo Nova-compute commands: \(Please exec these commands on HOST $host\)

echo

tap=tap${portid:0:11}

qbr=qbr${portid:0:11}

qvo=qvo${portid:0:11}

qvb=qvb${portid:0:11}

echo sudo nova-rootwrap /etc/nova/rootwrap.conf brctl addbr ${qbr}

echo sudo nova-rootwrap /etc/nova/rootwrap.conf brctl setfd ${qbr} 0

echo sudo nova-rootwrap /etc/nova/rootwrap.conf brctl stp ${qbr} off

echo sudo nova-rootwrap /etc/nova/rootwrap.conf ip link add ${qvb} type veth peer name ${qvo}

echo sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set ${qvb} up

echo sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set ${qvb} promisc on

echo sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set ${qvo} up

echo sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set ${qvo} promisc on

echo sudo nova-rootwrap /etc/nova/rootwrap.conf ip link set ${qbr} up

echo sudo nova-rootwrap /etc/nova/rootwrap.conf brctl addif ${qbr} ${qvb}

echo sudo nova-rootwrap /etc/nova/rootwrap.conf brctl addif ${qbr} ${tap}

echo sudo nova-rootwrap /etc/nova/rootwrap.conf ovs-vsctl --timeout=120 -- --if-exists del-port ${qvo} -- add-port br-int ${qvo} -- set Interface ${qvo} external-ids:iface-id=${portid} external-ids:iface-status=active external-ids:attached-mac=${mac} external-ids:vm-uuid=${device}

echo

echo

5     FAQ

1. qbo口是哪个服务进程在何时加入br-int的?

nova-compute在spawn时,通过libvirtdriver plug方法加入的。

2. neutron db中的nova port是那哪个服务进程在何时创建的?

nova-compute在创建虚机创建网络资源时通过neutron client create-port创建的。

3.创建虚机时出现no valid host可能有哪些原因?

4. ovs-agent如何知道虚机创建了,如何指定qvo与虚机的对应关系?

nova-compute将qvo加入br-int时,会配置port-uuid信息,通过ovsdb-monitor监控db变化,

通过uuid找到对应的neutron port。

5.如果nova-compute始终收不到network-vif-plug的event,虚机行为是怎样?

根据vif_plugging_is_fatal配置项决定创建虚机是否失败。

时间: 2024-10-30 08:58:27

nova与neutron交互的相关文章

nova boot代码流程分析(三):nova与neutron的交互(2)

继续<nova boot代码流程分析(三):nova与neutron的交互(1)>的分析. #/nova/virt/libvirt/driver.py:LibvirtDriver # NOTE(ilyaalekseyev): Implementation like in multinics # for xenapi(tr3buchet) def spawn(self, context, instance, image_meta, injected_files, admin_password,

openStack aio nova service-list neutron ext-list

neutron self-service 2 list agent to veirfy systemctl status neutron-server.service neutron-linuxbridge-agent.service neutron-dhcp-agent.service neutron-metadata-agent.service neutron-l3-agent.service openstack-nova-compute.service systemctl restart 

Openstack Ice-House 版本号说明--之中的一个 NOVA

OpenStack Icehouse在4.17正式公布,看了下release note,发现改变不小,说明openstack还是在高速发展中,有不少新的特性增加,也有些小的剔除.以下就我所关注的项目做个简单翻译,技术水平有限,眼界有限,哪里有错,还望各位大牛指出. 一.升级相关: 1.windows下环境变量不能是unicode,要使用 pbr 0.8避免这个BUGhttps://bugs.launchpad.net/pbr/+bug/1294246 2.log-config 更改为 log-c

发现 OpenStack: 架构、功能和交互

最近准备回归openstack阵营.一直想把oepnstack从最初的认识到全架构大概写一篇,却发现在developerworks中已经有了一篇.大家共勉 ================================================================================ OpenStack 是由 IBM® 和其他行业领导者推广的一个流行的开源云计算项目.本文将概述总体架构.各个模块的功能和它们之间的交互.本系列的其他文章将详细介绍各类 OpenSta

(转) 一次批量重启引发的Neutron网络故障

现场回顾 故事发生于某个下午,采用 salt 更新某集群的 neutron.conf (log 相关配置项) 并批量重启 neutron-openvswitch-agent(以下简称 neutron-ovs-agent),不久便有人反馈云主机宕机. 立即排查发现云主机并没有宕机,只是网络不通,大部分计算节点的 ovs 流表空空如也.Nova 和 Neutron 打出 ERROR 级别的日志. $ ovs-ofctl dump-flows br-bondNXST_FLOW repy (xid=0x

nova event机制分析

本文主要分析Nova的一个event机制,目前主要用于VIF plugin是的notification,可以实现Nova 和 Neutron直接VIF 状态信息的交互. 1. nova部分 vif_plugging_timeout配置参数的解释,用于定义创建VM时等待VIF准备好的时间 cfg.BoolOpt('vif_plugging_is_fatal', default=True, help="Fail instance boot if vif plugging fails"),

nova boot代码流程分析(五):VM启动从neutron-dhcp-agent获取IP与MAC

1.   network和subnet创建代码流程 [[email protected] ~(keystone_user1)]# neutron net-create demo-net [[email protected] ~(keystone_user1)]# neutron subnet-create  demo-net 1.1.1.0/24 --name demo-subnet --gateway 1.1.1.1 --enable_dhcp true 这里,我们主要分析上面两个命令的代码流

[ Openstack ] Openstack-Mitaka 高可用之 网络服务(Neutron)

目录 Openstack-Mitaka 高可用之 概述    Openstack-Mitaka 高可用之 环境初始化    Openstack-Mitaka 高可用之 Mariadb-Galera集群部署    Openstack-Mitaka 高可用之 Rabbitmq-server 集群部署    Openstack-Mitaka 高可用之 memcache    Openstack-Mitaka 高可用之 Pacemaker+corosync+pcs高可用集群    Openstack-M

8.CentOS7下Openstack-Train版本安装--网络服务neutron(控制节点)

1.创建neutron数据库 [[email protected] ~]# mysql -u root -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 918 Server version: 10.3.10-MariaDB MariaDB Server Copyright (c) 2000, 2018, Oracle, Maria