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 '{"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"}}' 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。
結束。
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網路過程:
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)結束。
程式碼路徑: 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)結束。
程式碼路徑: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
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配置項決定建立虛機是否失敗。