Nova 操作匯總(限 libvirt 虛機) [Nova Operations Summary]


本文梳理一下 Nova 主要操作的流程。

 0. Nova REST-CLI-Horizon 操作對照表

Nova 基本的 CRUD 操作和 extensions:

# 類別 Nova V2 REST API Action Nova CLI Horizon 解釋
  虛機操作 POST boot Launch Instance

啟動一個新的虛機

 http://www.cnblogs.com/sammyliu/p/4558638.html

    DELETE delete Terminate Instance

關閉和刪除一個虛機

  1. call dom.destroy
  2. call dom.undefineFlags
    confirmResize  resize-confirm  N/A

確認 resize 操作 

http://www.cnblogs.com/sammyliu/p/4572287.html

    revertResize  resize-revert N/A 

取消 resize 操作

http://www.cnblogs.com/sammyliu/p/4572287.html

    reboot  reboot [--hard]

Soft Reboot Instance

Hard Reboot Instance 

重啟虛機,具體分析見本文 1. 章節

    changePassword  root-password    libvirt driver 沒有實現
    resize  resize  Resize Instance 遷移虛機或者改變虛機的flavor: http://www.cnblogs.com/sammyliu/p/4572287.html
    rebuild  rebuild  Rebuild Instance  先調用 driver.destroy (destroy domain,detach volume connections,plug VIF), 然后再調用 driver.spawn
    createImage  image-create  N/A   快照。http://www.cnblogs.com/sammyliu/p/4468757.html
    os-start  start  Launch Instance  = hard reboot,見下面 1. 章節
    os-stop  stop  Shut Off Instance  call dom.destroy
  admin action pause  pause  Pause Instance  call dom.suspend
    unpause  unpause  Resume Instance  call dom.resume
    suspend  suspend  N/A
  1.  _detach_pci_devices
  2. _detach_sriov_ports
  3. dom.managedSave(0)
    resume  resume N/A 
  1.  get domain xml
  2. _create_domain_and_network
  3. attach pci devices
  4. attach sriov port
    migrate  migrate  N/A  http://www.cnblogs.com/sammyliu/p/4572287.html
    resetNetwork   N/A   libvirt 沒有實現
    injectNetworkInfo   N/A   Set up basic filtering (MAC, IP, and ARP spoofing protection),調用 _conn.nwfilterDefineXML(xml)
    lock  lock  N/A  直接在數據庫中 instance 上面設置 lock = true
    unlock  unlock  N/A  直接在數據庫中 instance 上面設置 lock = false
    createBackup  backup N/A 

 同 createImage,可以指定類型(daily 或者 weekly),和保存的 image 的最大數目,老的 image 會被刪除

{"backup_type": "daily", "rotation": "2", "name": "bk"}

    os-migrateLive  live-migration N/A   http://www.cnblogs.com/sammyliu/p/4572287.html
    os-resetState  reset-state  N/A  傳入 state 參數,直接修改數據庫中 instance 的狀態
  bare metal add_interface  baremetal-interface-add   TBD
    remove_interface  baremetal-interface-remove   TBD 
  cloudpipe update  cloudpipe-configure   TBD
  console os-getVNCConsole  get-vnc-console  Console

見本文第四章節

    os-getSPICEConsole  get-spice-console   TBD
    os-getRDPConsole  get-rdp-console   TBD 
    os-getSerialConsole     TBD 
    os-getConsoleOutput console-log  View Log  讀取 虛機的 console.log 文件並返回其內容;如果沒有這文件的話,則使用 “pty”,將其內容寫入到 consolue文件並返回其內容。
  delete restore  restore  Terminate Instance  Restore a previously deleted (but not reclaimed) instance。直接修改數據庫。
    forceDelete  force-delete  N/A

 有 snapshot,則全部刪除;然后從 DB 中刪除 instance.

  evacuate evacuate  evacuate    從 DB 中讀取 instance 數據,在一個新的主機上 rebuild。
  flavor access addTenantAccess  flavor-access-add  Flavor - Modify Access  修改 DB 中 flavor 表
    removeTenantAccess  flavor-access-remove  Flavor - Modify Access  修改 DB 中 flavor 表
  flavor manage delete  flavor-delete  Flavor - Delete Flavor 直接 DB 操作
    create  flavor-create  Flavor - Create Flavor  直接 DB 操作
  floating ip addFloatingIp  floating-ip-create  Associate Floating IP  調用 network_api.associate_floating_ip
    removeFloatingIp  floating-ip-delete  Disassociate Floating IP  調用 network_api.disassociate_floating_ip
  NIC addFixedIp  fixed-ip-reserve  

 參數 "networkId"。

  1. call network_api.add_fixed_ip_to_instance
  2. call firewall_driver.setup_basic_filtering
    removeFixedIp  fixed-ip-unreserve  

 參數 "address"。

  1. call network_api.remove_fixed_ip_from_instance
  2. call firewall_driver.setup_basic_filtering(instance, nw_info) 
  network associate disassociate_host      Associate or disassociate host or project to network。 call network_api.associate
    disassociate_project  network-disassociate    call network_api.associate
    associate_host  network-associate-host    call network_api.associate
  os network disassociate      call network_api.associate
  rescue rescue  rescue    見本文第二章節
    unrescue  unrescue    見本文第二章節
  security group addSecurityGroup  add-secgroup    call security_group_rpcapi.refresh_security_group_rules
    removeSecurityGroup  secgroup-delete    call security_group_rpcapi.refresh_security_group_rules
  shelve shelve  shelve    見本文第三章節
    shelveOffload  shelve-offload    見本文第三章節
    unshelve  unshelve    見本文第三章節

 

1. Reboot (重啟)

物理機有兩種重啟方式:一種從操作系統中重啟,一種直接先斷電然后再接通電源。虛機的重啟也有類似的兩種方式:Soft Reboot 和 Hard Reboot。nova reboot 命令在不使用 “-hard” 情況下,默認會 Soft Reboot,如果失敗則會 Hard reboot;如果使用了 “-hard”,則直接 Hard reboot。

1.1 Soft reboot

Soft reboot 完全依賴於虛機的操作系統和 ACPI。其過程為:

  1. Shutdown domain (domain.shutdown)
  2. Launch domain (domain.createWithFlags)

關於 shutdown API ,它會shutdown一個虛機,但是虛機的各種附件(object)依然可以使用,只是虛機的操作系統被停止了。注意,虛機的操作系統可能會忽略該請求。這時候,shutdown 不會成功(在 CONF.libvirt.wait_soft_reboot_seconds 指定的時間內,nova發現虛機沒有被 shutdown),得轉到 hard reboot 了。(Shutdown a domain, the domain object is still usable thereafter, but the domain OS is being stopped. Note that the guest OS may ignore the request.) 

1.2 Hard reboot

Hard reboot 比 Soft reboot 復雜、耗時長。其主要過程為:

  1. Destroy domain (virt_dom.destroy())。Destroy 和 Shutdown 兩個 API 的區別是:shutdown domain 以后,客戶機的磁盤存儲處於可用狀態,而且該 API 在命令發給 Guest OS 后立即返回,客戶程序需要不斷檢查其狀態來判斷是否shutdown 成功;而 destroy API 執行后,客戶機的所有資源都會被歸還給 Hypervisor (all resources used by it are given back to the hypervisor),它的過程是首先給客戶機發送一個terminate 指令比如SIGTERM,如果在一定的時間內未成功則直接發送 SIGKILL 指令將虛機殺掉。
  2. 根據 domain 的信息(instance, network_info, disk_info,image_meta, block_device_info)重新生成 domain 的配置 xml
  3. 根據 image 重新生成各鏡像文件(包括 disk,disk.local 和 disk.swap)
  4. 連接各個 volume
  5. 將各個 interface 掛到 OVS 上
  6. 重新生成和應用 iptales 規則
  7. Define domain (conn.defineXML)
  8. Launch domain (domain.createWithFlags)

可見,hard reboot 是真正的 reboot 一個虛機。來比較一下 hard reboot 前后的虛機的磁盤和xml 文件:

#reboot 前
root@compute2:/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd# ls -l total 2608 -rw-rw---- 1 root root 20126 Jun 10 12:38 console.log -rw-r--r-- 1 libvirt-qemu kvm 2162688 Jun 10 12:40 disk -rw-r--r-- 1 nova nova 246 Jun 10 07:54 disk.info -rw-r--r-- 1 libvirt-qemu kvm 393216 Jun 10 12:39 disk.local -rw-r--r-- 1 libvirt-qemu kvm 197120 Jun 10 07:54 disk.swap -rw-r--r-- 1 nova nova 3452 Jun 10 12:39 libvirt.xml
#reboot 后 root@compute2:
/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd# ls -l total 2608 -rw-rw---- 1 root root 20126 Jun 10 12:38 console.log -rw-r--r-- 1 libvirt-qemu kvm 2162688 Jun 10 12:57 disk -rw-r--r-- 1 nova nova 246 Jun 10 07:54 disk.info -rw-r--r-- 1 libvirt-qemu kvm 393216 Jun 10 12:57 disk.local -rw-r--r-- 1 libvirt-qemu kvm 197120 Jun 10 07:54 disk.swap -rw-r--r-- 1 nova nova 3452 Jun 10 12:57 libvirt.xml root@compute2:/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd# diff libvirt.xml libvirt.xml.ori 10c10 < <nova:creationTime>2015-06-10 04:57:25</nova:creationTime> #domain 除了創建時間不同別的都相同 --- > <nova:creationTime>2015-06-10 04:39:14</nova:creationTime> 84c84 < <source host="127.0.0.1" mode="bind" service="10002"/> --- > <source host="127.0.0.1" mode="bind" service="10001"/>

2. Rescue (拯救)和 Unrescue

Rescue 是個很有意思的功能。它的一個使用場景是,虛機的啟動盤的一個文件被誤刪除了導致無法再次啟動了,或者 admin 的密碼忘記了。Rescue 功能提供一個解決這類問題的手段。

執行 nova rescue 命令后的主要過程是:

(1)保存目前domain 的 xml 配置到 unrescue.xml 文件

(2)根據 image 重新生成啟動盤 disk.swap (大小不受 falvor.root_disk_size 控制,盡可能小的一個文件)

root@compute2:/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd# qemu-img info disk.rescue
image: disk.rescue
file format: qcow2
virtual size: 39M (41126400 bytes) #不是 falovr 里面定義的 1G 大小
disk size: 1.6M
cluster_size: 65536
backing file: /var/lib/nova/instances/_base/fbad3d96a1727069346073e51d5bbb1824e76e34
Format specific information:
    compat: 1.1
    lazy refcounts: false

(3)構造一個新的 domain 的 xml 配置,使用 disk.rescue 做啟動盤,將原來的 disk 掛載到該 domain,其他的盤和volume不會被掛載。

   <disk type="file" device="disk">
      <driver name="qemu" type="qcow2" cache="none"/>
      <source file="/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk.rescue"/> #新構造的啟動盤
      <target bus="virtio" dev="vda"/>
    </disk>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2" cache="none"/>
      <source file="/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk"/> #原來的啟動盤
      <target bus="virtio" dev="vdb"/>
    </disk>

(4)將原來的 domain destroy 掉 (virt_dom.destroy)

(5)定義新的 domain (conn.defineXML(xml))

(6)啟動新的 domain (domain.createWithFlags)

至此,nova rescue 的過程完成。用戶可以 ssh 到新的虛機,修改 “Vdb“分區中的受損害的文件。然后執行 ”nova unrescue“命令。其主要過程是:

(1)讀取之前保存的 unrescue.xml 文件

(2)將 rescued domain destroy 掉

(3)定義和啟動新的domain(同上面5和6)

(4)刪除 unrescue.xml 文件

注意,這時候文件夾中的 libvirt.xml 文件和新運行的 domain 的 xml 不一致,因為代碼中沒有將新的 domain 的xml 寫到該文件。

3. Shelve (擱置)和 unshelve

當一個虛機不需要使用的時候,可以將其 shelve 起來。該操作會創建該虛機的一個快照並傳到 Glance 中,然后在 Hypervisor 上將該虛機刪除,從而釋放其資源。

其主要過程為:

  1. destroy 虛機 (virt_dom.destroy())
  2. snapshot 該 domain
  3. 如果 CONF.shelved_offload_time == 0 的話,將domain 的各種資源(interface,volume,實例文件等),然后將其undefine (virt_dom.undefine())

其只存在於數據庫和 Glance 中。運行 nova list 能看到一條記錄:

| 8352e969-0a25-4abf-978f-d9d0ec4de0cd | vm11               | SHELVED_OFFLOADED | -          | Shutdown    | demo-net2=10.0.10.14; demo-net=10.0.0.41 |

運行 glance image-list 能看到其image:

| 6ed6eb92-ce42-46d1-ab46-259e3e235304 | vm11-shelved   | qcow2       | bare             | 19988480 | active |

能看到該 image 的 instance 相關的屬性:

s1@controller:~$ glance image-show 6ed6eb92-ce42-46d1-ab46-259e3e235304
+---------------------------------------+--------------------------------------+
| Property                              | Value                                |
+---------------------------------------+--------------------------------------+
| Property 'base_image_ref'             | bb9318db-5554-4857-a309-268c6653b9ff |
| Property 'image_location'             | snapshot                             |
| Property 'image_state'                | available                            |
| Property 'image_type'                 | snapshot                             |
| Property 'instance_type_ephemeral_gb' | 1                                    |
| Property 'instance_type_flavorid'     | 129f237e-8825-49fa-b489-0e41fb06b70e |
| Property 'instance_type_id'           | 8                                    |
| Property 'instance_type_memory_mb'    | 50                                   |
| Property 'instance_type_name'         | tiny2                                |
| Property 'instance_type_root_gb'      | 1                                    |
| Property 'instance_type_rxtx_factor'  | 1.0                                  |
| Property 'instance_type_swap'         | 30                                   |
| Property 'instance_type_vcpus'        | 1                                    |
| Property 'instance_uuid'              | 8352e969-0a25-4abf-978f-d9d0ec4de0cd |
| Property 'network_allocated'          | True                                 |
| Property 'owner_id'                   | 74c8ada23a3449f888d9e19b76d13aab     |
| Property 'user_id'                    | bcd37e6272184f34993b4d7686ca4479     |

Unshelve 是 shelve 的反操作。它的主要過程是:

  1. 從 DB 中獲取 network_info 和 block_device_info
  2. 從 Glance 中獲取 image
  3. 象新建一個虛擬那樣 spawn 新的虛機
  4. 調用 image API 將 image 刪除 

4. VNC (VNC 連接)

VNC 操作的過程:(來源

 

(1)用戶查詢 VNC 的訪問 URL。

Nova CLI 對應的命令為 “nova get-vnc-console <server> <console-type>”。 REST API 的數據格式為:{"os-getVNCConsole": {"type": "novnc"}} 

“type” 參數值可以是 “novnc” 或者 “xvpvnc”。

(2)通過 RPC 調用虛機所在的 node 上的 Nova 生成一個 UUID(長度為 4)格式的 token,以及格式為 ‘<base_url>?token=<token>' 的 Access URL。

  • base_url 從 CONF.novncproxy_base_url (比如 http://192.168.1.20:6080/vnc_auto.html)或者 CONF.xvpvncproxy_base_url 讀取。

(3)本地Nova 調用 libvirt driver 從 domain xml 中獲取 port,比如下面例子中的 5900,以及從 confi.vncserver_proxyclient_address 獲取 host。 

<graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0' keymap='en-us'>
<listen type='address' address='0.0.0.0'/>
</graphics>

(4)通過 RPC,調用 consoleauth 的 authorize_console 方法,它將 Access URL, host,port 保存到 memcached。

(5)返回 Access URL 給客戶端,比如 http://192.168.1.20:6080/vnc_auto.html?token=8dc6f7cb-2e2d-4fbe-abab-3334fe3a19dc

在 Contoller 節點上運行着一個service “/usr/bin/python /usr/bin/nova-novncproxy --config-file=/etc/nova/nova.conf”。該 service 默認在 6080 端口(可由 CONF.novncproxy_port 配置)監聽來自所有地址(可由 CONF.novncproxy_host 配置)的請求。

(6)在客戶端瀏覽器上打開 Access URL,由 Controller 上的 nova-novncproxy 接收並處理

(7)nova-novncproxy 通過 RPC 調用 consoleauth.check_token() 方法,獲取 console_type 和 port 等 connect info。期間還會到目的node上去校驗這些信息。

 {u'instance_uuid': u'7c53af66-765b-48f3-b8a2-a908feb63968', u'internal_access_path': None, u'last_activity_at': 1434670235.591856, u'console_type': u'novnc', u'host': u'192.168.1.15', u'token': u'10bffd07-e11c-48bb-880a-bc1a49c871d7', u'port': u'5900'}

(8)連接到目的 node,握手,開始 proxying。

 與 NOVNC 有關的配置參數:

節點 配置文件 參數 默認配置 說明
Controller /etc/nova/nova.conf novncproxy_port 6080 /usr/bin/nova-novncproxy 服務所在的節點(通常是 Controller 節點)上 該 service 所監聽的端口。奇怪的是 nova 文檔中沒說明該配置參數。
novncproxy_host  0.0.0.0 nova-novncproxy service 所監聽的請求來源地址。0.0.0.0 表示接收所有來源的請求。奇怪的是 nova 文檔中沒說明該配置參數。
nova-compute /etc/nova/nova.conf vncserver_proxyclient_address   虛機所在的 nova compute 節點的 management 網卡的 IP 地址
vncserver_listen 127.0.0.1 虛機所在的 nova compute 節點的 vnc service 所監聽的端口,需要修改默認配置為其 0.0.0.0
novncproxy_base_url

http://127.0.0.1:6080/
vnc_auto.html

nova 客戶端通過 get_vncconsole 命令獲取到的訪問虛機的 VNC URL。需要修改其值為 

http://<nova-novncproxy-node-management-interface-ip>:<nova-novncproxy-node-nova.conf.novncproxy_port>/vnc_auto.html 比如 http://192.168.1.20:6080/
vnc_auto.html

vnc_enabled

true

使得虛機能夠對外提供 VNC 服務

5. Evacuate (移機)

作用:當一個 node down 掉后,在新的 node 上根據其 DB 中保存的信息重新 build down node 上虛機。這個往往在虛機 HA 方案中用到。它盡可能地將原來的虛機在新的主機上恢復:

  • 虛機的配置:從 DB 中獲取,包括 image,block,network 等
  • 虛機的數據:如果使用共享存儲,則使用共享存儲上的虛機數據;如果不使用共享存儲,則無法恢復數據
  • 內存狀態:無法恢復

因此,HA 方案中,應該盡可能地將虛機的數據文件放在共享存儲上,否則,恢復出來的虛機的價值非常有限。

 

Nova CLI:usage: nova evacuate [--password <password>] [--on-shared-storage] <server> [<host>]

要求:

(1)必須指定和虛機的 host 不同的 host,否則將報錯“The target host can't be the same one”。

(2)虛機的host 必須處於不可用狀態,否則將報錯 “Compute service of compute2 is still in use.”

(3)可以指定新的 admin password,不指定的話,nova 將生成一個隨機密碼

(4)參數 on-shared-storage 表示虛機的 instance folder 是不是在共享存儲上。

主要步驟:

(1)在做完以上各種參數檢查后,調用 Conductor 的 方法:

return self.compute_task_api.rebuild_instance(context, instance=instance, new_pass=admin_password, injected_files=None, image_ref=None,
orig_image_ref=None, orig_sys_metadata=None, bdms=None, recreate=True, on_shared_storage=on_shared_storage, host=host)

如果 host 為none 的話,conductor 將調用 scheduler 的方法選擇一個 host。

(2)接着調用 nova compute 的 rebuild_instance 方法。該方法從系統(DB)中獲取已有的數據,然后根據這些已有的 metadata 重新構造domain。“A 'rebuild' effectively purges all existing data from the system and remakes the VM with given 'metadata' and 'personalities'.”

  • 獲取 image_ref,再獲取 image meta
  • 獲取 network_info 並在新的 host 上構造網絡
  • 獲取 BlockDeviceMappingList
  • 獲取 block_device_info

(3)然后調用 virt driver 的 rebuild 方法,但是 libvirt 沒有實現該方法,轉而調用 _rebuild_default_impl 方法。該方法:

  • 從 volume 端斷開其與原來 host 的連接
  • 調用 driver.spawn 方法構造新的 domain,依次創建 image(如果 on_shared_storage = false 的話,則重新下載 image, 構造 instance folder;如果 on_shared_storage = true 的話,則直接使用共享存儲上的 instance folder。這也可見使用共享存儲的優勢),network 和 domain,並設置 domain 的狀態和之前一致。

(4)在壞了的 host 被重啟后,nova-compute 服務調用 _destroy_evacuated_instances 方法來找到 evacuated instances 並將它們刪除:

  • 調用 libvirt 找到該 host 上所有 domains,然后在 nova db 中一一查找其狀態,過濾出 “deleted” 為 false 的 domains
  • 如果instance.host 不是本機,而且 instance.task_state 不是 { MIGRATING,RESIZE_MIGRATING,RESIZE_MIGRATED,RESIZE_FINISH} 之一,則刪除該 domain,以及 network,block device 以及 instance folder。

總之,在使用共享存儲的情況下,evacuate 出來的新的 domain 除了臨時盤上的數據外,它和之前的 domain 的數據是一樣的了,但是內存狀態除外。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM