歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> BSD >> 在 FreeBSD bhyve 下運行 Windows

在 FreeBSD bhyve 下運行 Windows

日期:2017/2/28 13:55:36   编辑:BSD

正如我之前所寫的那樣,FreeBSD 下的虛擬機管理程序 bhyve 即將支持 Windows 了。在其通過 FreeBSD Virtualization 郵件列表公布時,FreeBSD 11.0-CURRENT r288524 版已對其正式支持。不久之後,Windows 的外交人員 Michael Dexter 就在 FreeBSD Wiki 上編寫了一個關於在 bhyve 下運行 Windows 的很棒的指引手冊。

在 bhyve 下運行 Windows 的秘密武器就是全新的 UEFI 支持。這真是個相當棒的消息,因為當你在 bhyve 中采用 UEFI 時, 你已不必先在 bhyveload 或 grub-bhyve 中加載操作系統。下面是在命令行運行一個 Windows bhyve 實例的示例:

bhyve \
-c 2 \
-s 0,hostbridge \
-s 3,ahci-hd,windows2016.img \
-s 4,ahci-cd,install.iso \
-s 10,virtio-net,tap0 \
-s 31,lpc \
-l com1,/dev/nmdm0A \
-l com2,/dev/nmdm1A \
-l bootrom,BHYVE_UEFI_20151002.fd \
-m 2G -H -w \
windows2016

在我得業余時間裡,我正在開發一個叫做 iohyve 小的 shell 腳本,所以當此支持到來時,我欣喜若狂。我開始開發 iohyve 是因為當進行沙箱測試時,我不想使用 Oracle 的 VirtualBox。有時我喜歡點擊一些不可靠的鏈接並寫郵件給濫用的部門並標記為垃圾郵件,我希望讓盡可能多的任何可能的潛在惡意軟件遠離我。由於大多數惡意軟件都是為 Windows 用戶所寫,在 bhyve 中支持它意味著我已經慢慢的接近實現這一目標了。現在 iohyve 還不能將客戶機放在優秀的虛擬 NAT 網絡,但我最近已經把 UEFI 支持 加入到了 FreeBSD ports 中的 iohyve v0.7 版本了。對於今天這個教程,我將使用 GitHub 上的版本來完成在 FreeBSD 中創建一個 bhyve Windows 客戶機的任務,因為這個 iohyve UEFI 命令的版本的 bug 比較少。請注意,由於 UEFI 固件還是很新的,是實驗性質的,所以 iohyve 對它的支持也是實驗性質的。現在的局限在於你只能有一個 HDD,一個虛擬 NIC(使用 tap 設備),以及沒有支持 pass-through。其他操作系統若通過 bhyveload 或 grup-bhyve 命令啟動則可以支持多個虛擬 HDD,甚至是 passthrough 支持。

主機和安裝 ISO 准備。

為了利用在 bhyve 中啟動芯片(UEFI)的功能,你需要運行FreeBSD 11.0-CURRENT(至少是r288524版本)。自從 iohyve 使用了ZFS, 如果你還在運行 11-CURRENT,你真應該跳過它,使用 zpool 去設置。在我的筆記本上,我選擇使用 Root on ZFS 來安裝FreeBSD,使用它非常簡單。稍後,我將會進入 iohyve 的設置。在這之前,我會先運行 bhyve,我需要先創建一個自定義的 Windows 安裝 ISO。因為 bhyve 不能輸出視頻,我們必須創建一個“無人值守的”安裝 ISO。因為我們會重新制作新的 ISO,我們將會在重新制作的 ISO 中安裝 VirtIO NIC 驅動來確保 Windows guest 能連接到網絡。

正如我前面提到的,FreeBSD 的 wiki 條目 細節已經達到了這種程度。自從 bhyve 開始支持 Windows 之後,為了嘗試在 bhyve 下運行不同版本的 Windows 操作系統,我編寫了一系列小的腳本和文件。我發現自己一遍又一遍的嘗試不同的 AutoUnattend.xml 文件。這個 XML 文件基本上是當在裸機上安裝 Windows 時一系列點擊按鈕的“響應”。我在一個被我稱為 Yabs 的腳本裡簡化了這些流程。我會在本教程中使用那些腳本,但我會隨時檢查並與 wiki 上的文章同步。你也需要找一個 Windows ISO 安裝文件的副本。在本教程中,我將使用 Windows 2008,盡管我也已經用 Windows 2012 試過了。

-用 git 克隆 Yabs 的 repo,並開始你的初始工作目錄。

$ git clone https://github.com/pr1ntf/YetAnotherBhyveScript.git
Cloning into 'YetAnotherBhyveScript'...
remote: Counting objects: 22, done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 22 (delta 9), reused 17 (delta 4), pack-reused 0
Unpacking objects: 100% (22/22), done.
Checking connectivity... done.$ mv YetAnotherBhyveScript/ win2k8auto$ cd win2k8auto/

-使用 fetch 命令從 Peter 那裡取得固件,並從 Fedora Project 取得驅動。我將使用 0.1-94 版驅動,因為較新版的驅動在 Windows 2008 下不能正常工作。

$ fetch https://people.freebsd.org/~grehan/bhyve_uefi/BHYVE_UEFI_20151002.fd
$ fetch https://fedorapeople.org/groups/virt/virtio-win/deprecated-isos/archives/virtio-win-0.1-94/virtio-win-0.1-94.iso

-我找到的 ISO 安裝文件叫做 Win2k8R2.iso,其目錄內容如下:

$ ls
BHYVE_UEFI_20151002.fd  Win2k8-AutoUnattend.xml extract.sh              remaster.sh             yabs.sh
README.txt              Win2k8R2.iso            null.iso                virtio-win-0.1-94.iso

-我們現在必須修改 extract.sh 腳本來指向正確的位置。要注意運行 extract.sh 需要 FreeBSD 的 Port archivers/pz7ip。我的文件如下:

#!/bin/sh

# Extract important stuff to remaster folder

folder=win2k8
iso=Win2k8R2.iso
drivers=virtio-win-0.1-94.iso

mkdir -p ${folder}/virtio

7z x ${iso} -o${folder}

tar xf $drivers -C ${folder}/virtio

-在我們執行 ./extract.sh 之後我們可以將 AutoUnattend.xml 文件復制到我們的 win2k8 目錄下。Yabs 中包含的 AutoUnattend.xml 文件會將管理員密碼設置為 R3dm0nd!,並會將默認網卡 IP 設置為 192.168.0.111 並具有指定網關和子網掩碼。因此一定要先對其進行修改。你可以在此文件中刪除第二個 <SynchronousCommand wcm:action="add">。(在第一次登陸時執行這個命令 netsh interface ipv4 set address name="local area connection" source=static address=192.168.0.111 mask=255.255.255.0 gateway=192.168.0.1)。

$ cat Win2k8-AutoUnattend.xml
<?xml version="1.0" encoding="utf-8"?><unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="windowsPE">
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DiskConfiguration>
<Disk wcm:action="add">
<DiskID>0</DiskID>
<WillWipeDisk>true</WillWipeDisk>
<CreatePartitions>
<CreatePartition wcm:action="add">
<Order>1</Order>
<Size>400</Size>
<Type>EFI</Type>
</CreatePartition>
<CreatePartition wcm:action="add">
<Order>2</Order>
<Size>128</Size>
<Type>MSR</Type>
</CreatePartition>
<CreatePartition wcm:action="add">
<Order>3</Order>
<Extend>true</Extend>
<Type>Primary</Type>
</CreatePartition>
</CreatePartitions>

<ModifyPartitions>
<!-- EFI system partition (ESP) -->
<ModifyPartition wcm:action="add">
<Order>1</Order>
<PartitionID>1</PartitionID>
<Label>System</Label>
<Format>FAT32</Format>
</ModifyPartition>

<!-- Windows partition -->
<ModifyPartition wcm:action="add">
<Order>2</Order>
<PartitionID>3</PartitionID>
</WindowsFeatures>
<Themes>
<ThemeName>Classic Theme</ThemeName>
<DefaultThemesOff>true</DefaultThemesOff>
</Themes>
<ShowWindowsLive>false</ShowWindowsLive>

<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<CommandLine>cmd /C bcdedit /emssettings emsport:1 emsbaudrate:115200</CommandLine>
<Description>Enable EMS</Description>
<Order>1</Order>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<CommandLine>netsh interface ipv4 set address name="local area connection" source=static
address=192.168.0.111 mask=255.255.255.0 gateway=192.168.0.1</CommandLine>
<Order>2</Order>
</SynchronousCommand>
</FirstLogonCommands>
</component>
</settings>

<settings pass="offlineServicing">
<component name="Microsoft-Windows-PnpCustomizationsNonWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="NonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DriverPaths>
<PathAndCredentials wcm:action="add" wcm:keyValue="1">
<Path>d:\virtio</Path>
</PathAndCredentials>
</DriverPaths>
</component>
</settings></unattend>$ cp Win2k8-AutoUnattend.xml win2k8/AutoUnattend.xml

-現在我們按照所有正確的位置修改 remaster.sh 腳本來制作我們的無人值守 ISO 安裝文件。執行 ./remaster.sh 後所有的東西都會打包在一個不錯的 ISO 文件中。它需要 sysutils/cdrtools-devel port。我的如下:

#!/bin/sh

# Remaster new ISO

folder=win2k8
iso=win2k8.iso

mkisofs \
-b boot/etfsboot.com -no-emul-boot -c BOOT.CAT \
-iso-level 4 -J -l -D \
-N -joliet-long \
-relaxed-filenames -v \
-V "Custom" -udf \
-boot-info-table -eltorito-alt-boot -eltorito-platform 0xEF \
-eltorito-boot efi/microsoft/boot/efisys_noprompt.bin \
-no-emul-boot \
-o ${iso} ${folder}

iohyve 的安裝和准備

現在我們的工作目錄看起來應該是這樣的:

$ ls
BHYVE_UEFI_20151002.fd  Win2k8R2.iso            remaster.sh             win2k8.iso
README.txt              extract.sh              virtio-win-0.1-94.iso   yabs.sh
Win2k8-AutoUnattend.xml null.iso                win2k8

我們可以繼續安裝 iohyve 並為我們的 Windows 安裝過程做准備。如前所述,我們要使用 GitHub 上的版本,而不是 FreeBSD ports 中的版本。 執行 iohyve version 命令會輸出 0.7.1。

$ git clone https://github.com/pr1ntf/iohyve.git
Cloning into 'iohyve'...
remote: Counting objects: 904, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 904 (delta 0), reused 0 (delta 0), pack-reused 901
Receiving objects: 100% (904/904), 231.14 KiB | 0 bytes/s, done.
Resolving deltas: 100% (505/505), done.
Checking connectivity... done.$ cd iohyve/$ sudo make install clean
Password:
gzip -cn iohyve.8 > iohyve.8.gz
mkdir -p /usr/local/sbin
install -c -m 555 /usr/home/pr1ntf/iohyve/iohyve /usr/local/sbin/
install -c /usr/home/pr1ntf/iohyve/rc.d/* /usr/local/etc/rc.d/
install -c iohyve.8.gz /usr/local/man/man8/
rm -f iohyve.8.gz iohyve.8.cat.gz$ cd ~$ iohyve version
iohyve v0.7.1 2015/12/08 Im Here for the Party Edition

現在我們需要告訴 iohyve 三件事來設置它。

  • Zpool 存儲池存儲的 iohyve 數據集。
  • 以太網接口連接的所有 tap 設備可以連接的硬編碼(當前)bridge0 設備。
  • 告訴 iohyve 去加載 nmdm 及操作 iohyve 所需的 vmm 內核模塊。

因為我們想要讓 iohyve 在我每次啟動電腦的時候都會設置網絡和內核模塊,我會將 iohyve 的設置分為兩部分:為 zpool 執行 iohyve setup pool=zroot 命令,然後修改主機上的 /etc/rc.conf 文件並為接口和模塊執行 service iohyve start 命令。

因為我的默認以太網接口是 em0,於是我在主機的 /etc/rc.conf 文件中添加了下面的幾行代碼。

iohyve_enable="YES"
iohyve_flags="kmod=1 net=em0"

現在我可以執行 iohyve setup pool=zroot 命令和 service iohyve start 命令了:

$ sudo iohyve setup pool=zroot
Setting up iohyve pool...$ sudo service iohyve start
Starting iohyve guests...
Loading kernel modules...
Seting up bridge0 on em0...
net.link.tap.up_on_open: 1 -> 1

在我們可以創建我們的 Windows iohyve 客戶機之前,我們需要盡早在我們的 win2k8auto 文件夾中做以下三件事。

  • 最重要的是,我們需要一個秘密武器。我們需要 Peter 和 nahanni 已經提供給 FreeBSD 社區的 BHYVE_UEFI_20151002.fd UEFI 固件文件。
  • 我們需要我們早先已經創建的 win2k8.iso 無人值守 Windows ISO 安裝文件。
  • 由於在這種方式中固件與 Windows 交互時會出現一個異常行為,我們會需要一個基本上是空白光盤的 null.iso 文件。

為了實現這一點,我們可以使用 iohyve cpiso 和 iohyve cpfw 命令:

$ ls
BHYVE_UEFI_20151002.fd  Win2k8R2.iso            remaster.sh             win2k8.iso
README.txt              extract.sh              virtio-win-0.1-94.iso   yabs.sh
Win2k8-AutoUnattend.xml null.iso                win2k8$ sudo iohyve cpiso win2k8.iso
Password:
Copying win2k8.iso from win2k8.iso...$ sudo iohyve cpiso null.iso
Copying null.iso from null.iso...$ sudo iohyve cpfw BHYVE_UEFI_20151002.fd
Copying BHYVE_UEFI_20151002.fd from BHYVE_UEFI_20151002.fd...$ iohyve isolist
Listing ISO's...
null.iso
win2k8.iso$ iohyve fwlist
Listing Firmware...
BHYVE_UEFI_20151002.fd

Windows 客戶機的創建和准備

首先我們可以使用 32G 大小的虛擬 HDD 創建一個叫做 win2k8 的新的客戶機。

$ sudo iohyve create win2k8 32G
Creating win2k8...

現在我們需要在客戶機上設置一些屬性,以便 bhyve 可以正常的啟動客戶機。

$ iohyve fwlist
Listing Firmware...
BHYVE_UEFI_20151002.fd$ sudo iohyve set win2k8 fw=BHYVE_UEFI_20151002.fd bargs="-H -w" ram=1024M
Setting win2k8 fw=BHYVE_UEFI_20151002.fd...
Setting win2k8 bargs=-H -w...
Setting win2k8 ram=1024M...$ iohyve getall win2k8
Getting win2k8 props...
description Tue_Dec__8_10:30:51_MST_2015
fw BHYVE_UEFI_20151002.fd
ram 1024M
os default
cpu 1
size 32G
bargs -H_-w
loader bhyveload
name win2k8
boot 0
tap tap0
persist 1
con nmdm0
autogrub \ninstall yes

現在我們可以開始第一次引導安裝了。

Windows 安裝過程

Windows 的安裝過程分為三個主要的階段:

  • 第一個安裝階段(從 ISO 安裝文件中復制文件)
  • 第二個安裝階段(Windows 實際解壓並安裝一些東西)
  • 第三個安裝階段(Windows 執行在 AutoUnattend.xml 中設置的“第一次登陸”命令)

在第一階段開始之前,我喜歡打開另一個控制台並執行 iohyve console win2k8 命令。

$ sudo iohyve console win2k8
Password:
Starting console on win2k8...
~. to escape console [uses cu(1) for console]Connected

現在我們可以通過 iohyve uefi 命令開始安裝 win2k8 客戶機了。它應該會馬上開始。

$ iohyve isolist
Listing ISO's...
null.iso
win2k8.iso$ sudo iohyve uefi win2k8 win2k8.iso

切換到你的其他控制台,過一會你應該會看到 Windows SAC:

Computer is booting, SAC started and initialized.

Use the "ch -?" command for information about using channels.
Use the "?" command for general help.


SAC>
EVENT: The CMD command is now available.
SAC>
EVENT: A new channel has been created. Use "ch -?" for channel help.
Channel: SACSetupAct
SAC>
EVENT: A new channel has been created. Use "ch -?" for channel help.
Channel: SACSetupErr
SAC>

你可以按 [Esc]+[Tab] 鍵然後回車來切換到顯示了安裝細節的 SACSetupAct 控制台。Calling WIMApplyImage 的部分會需要執行一段時間才會退出。

:\ProgramData\] doesn't exist; no need to move it before applying image.2015-12-08 10:51:09, Info IBS MoveOldOSFiles:File/folder [E:\Recovery\] doesn't exist; no need to move it before applying image.2015-12-08 10:51:09, Info IBS MoveOldOSFiles:File/folder [E:\Users\] doesn't exist; no need to move it before applying image.2015-12-08 10:51:09, Info IBS MoveOldOSFiles:File/folder [E:\Windows\] doesn't exist; no need to move it before applying image.2015-12-08 10:51:09, Info [0x06412c] IBSLIB SetCheckpoint: Checkpoint("WinPEArchiveOldWindowsFoldersStartCheckpoint") in progress...2015-12-08 10:51:09, Info [0x06412e] IBSLIB SetCheckpoint: Checkpoint "WinPEArchiveOldWindowsFoldersStartCheckpoint" successfully set.2015-12-08 10:51:09, Info [0x06412c] IBSLIB SetCheckpoint: Checkpoint("WinPEArchiveOldWindowsFoldersDoneCheckpoint") in progress...2015-12-08 10:51:09, Info [0x06412e] IBSLIB SetCheckpoint: Checkpoint "WinPEArchiveOldWindowsFoldersDoneCheckpoint" successfully set.2015-12-08 10:51:09, Info [0x06412c] IBSLIB SetCheckpoint: Checkpoint("WinPEImageApplyReadyCheckpoint") in progress...2015-12-08 10:51:09, Info [0x06412e] IBSLIB SetCheckpoint: Checkpoint "WinPEImageApplyReadyCheckpoint" successfully set.2015-12-08 10:51:09, Info [0x06009e] IBS DeployWIMImage:Calling IDepWIMImageResolved::Apply...2015-12-08 10:51:10, Info [0x0606cc] IBS Calling WIMApplyImage (flags = 0x184)...

安裝程序之後會繼續將一些驅動程序文件復制到虛擬 HDD 中,之後你可以看到屏幕停在了下面的信息。需要注意的是,如果它似乎被凍結在了那裡,那麼客戶機可能已經完成了它的第一個階段安裝並關機了。

Name: SACDescription: Special AdminisType: VT-UTF8Channel GUID: 8472e3a1-9ddc-11e5-9c07-806e6f6e6963Application Type GUID: 63d02270-8aa4-11d5-bccf-806d6172696fPress <esc><tab> for next channel.Press <esc><tab>0 to return to the SAC channel.Use any other key to view this channel.

在第一個控制台上面,檢查並確保客戶機關機了。

$ iohyve list
Guest VMM? Running? rcboot? Description
win2k8 YES NO NO Tue_Dec__8_10:30:51_MST_2015

從上面的信息我們可以看到 Running? 標志被設置為了 NO,這意味著客戶機已經被關閉了。我們還需要運行 iohyve destroy win2k8 來從 VMM? 中移除它,不然客戶機將在第二個安裝階段失敗。

$ sudo iohyve destroy win2k8
Destroying win2k8...errno = 37

現在我們可以運行第二個階段了:

$ sudo iohyve uefi win2k8 null.iso

如果你切換到了 SAC 控制台你可以改變 SACSetupAct 引導以及查看屏幕上滾過的東西。這個步驟是非常迅速的,而且有時候你並不能捕捉到 SACSetupAct 引導,所以當客戶機關閉的時候你只能留下一個看起來如下的屏幕。

Setup is updating registry settings...
EVENT: A new channel has been created. Use "ch -?" for channel help.
Channel: SACSetupAct
SAC>
EVENT: A new channel has been created. Use "ch -?" for channel help.
Channel: SACSetupErr
SAC>
EVENT: The CMD command is now available.
SAC>
EVENT: A channel has been closed.
Channel: SACSetupAct
SAC>
EVENT: A channel has been closed.
Channel: SACSetupErr
SAC>
The SAC will become unavailable soon. The computer is shutting down.

SAC>

切換到你的第一個控制,檢查以確保其再次關閉,並再次移除它。然後,你可以開始第三個階段的安裝,並最終第一次啟動 Windows。

$ iohyve list
Guest VMM? Running? rcboot? Description
win2k8 YES NO NO Tue_Dec__8_10:30:51_MST_2015$ sudo iohyve destroy win2k8
Destroying win2k8...errno = 37$ sudo iohyve uefi win2k8 null.iso

第一次登陸安裝階段確實需要相當多的時間來完成,但最終,你的屏幕上會顯示如下信息:

Computer is booting, SAC started and initialized.

Use the "ch -?" command for information about using channels.
Use the "?" command for general help.


SAC>
EVENT: The CMD command is now available.
SAC>

如果我運行 SAC 命令 i,我可以看到在之前的 AutoUnattend.xml 文件中設置的客戶機的 IP 地址。默認情況下,Windows 客戶機無法 ping 通網絡,但執行 nmap 192.168.0.111 將會顯示 Windows 遠程桌面可用。

SAC>i
Net: 12, Ip=192.168.0.111 Subnet=255.255.255.0 Gateway=192.168.0.1

就是這樣!你現在可以用你慣用的遠程桌面客戶端使用你在 AutoUnattend.xml 中設置的默認密碼 R3dm0nd! 去連接客戶機的 Administrator 帳戶了。

安裝後你可以做的一些很酷的東西

盡管 iohyve uefi 功能尚未被正式支持,你依然可以使用內置的 iohyve 工具為 Windows 客戶機做一些很酷的關於動態文件系統(ZFS)的一些事情,比如在安裝更新之前創建快照:

$ sudo iohyve snap win2k8@preupdate
Password:
Taking snapshot win2k8@preupdate$ iohyve snaplist
win2k8@preupdate

你也可以制作一個這個客戶機的獨立的拷貝,一旦你制作了這個鏡像,你就可以不必一遍又一遍的執行 Windows 的安裝過程了:

$ sudo iohyve clone win2k8 win2k8-deploy
Cloning win2k8 to win2k8-deploy$ iohyve list
Guest VMM? Running? rcboot? Description
win2k8 YES NO NO Tue_Dec__8_10:30:51_MST_2015
win2k8-deploy NO NO NO Tue_Dec__8_11:34:38_MST_2015

英文原文:Running Windows under FreeBSD's bhyve

Copyright © Linux教程網 All Rights Reserved