先介绍一下nova命令中与网络相关的一些参数。
usage: nova boot [--flavor [--image-with [--snapshot [--max-count [--file [--user-data [--availability-zone [--security-groups [--block-device-mapping [--block-device key1=value1[,key2=value2...]] [--swap [--ephemeral size= [--hint [--nic [--config-drive |
其中,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
|
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 [--fixed-ip nova interface-detach |
命令示例:
绑定一个端口、网络或者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端口: [root@node-82 ~]# 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 | +------------+--------------------------------------+--------------------------------------+--------------+-------------------+ |
nova主要服务包括:
nova-api:对外提供rest-api。
nova-conductor:用于分发消息。
nova-scheduler:在创建虚机时,选择计算节点。
nova-compute:在计算节点上运行,负责管理虚机的生命周期。
用户创建虚机的命令到达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)结束。
删除虚机相对于创建虚机比较简单,不重点分析了。
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
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配置文件中都没有定义。
在查看代码时,经常可以看到网络相关变量,如果不知道数据结构代码比较难理解。
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是网络名称,
我们可能会遇到虚机是存在的,但底层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 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
|
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配置项决定创建虚机是否失败。