1. 程式人生 > >nova與neutron互動

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配置項決定建立虛機是否失敗。