新创建的Windows虚拟机如果不能通过DHCP获取IP,我们就需要登录到虚拟机内手动配置,很麻烦。这个工作能自动化最好,为Windows虚拟机进行初始化通常有两种思路:
1. 通过cloudbase-init,这个是cloud-init的Windows版本。Cloudbase-init需要类似OpenStack等云平台的metadata service获取初始化数据,如果我们实际环境中没有使用这种复杂的管理平台来管理KVM虚拟机,cloudbase-init用起来就比较麻烦,需要自己构建metadata。
2. 内置初始化脚本。在系统内编写脚本,并添加到开机启动。虚拟机开机以前,在宿主机上通过guestfs工具把初始化脚本需要的数据拷进虚拟机磁盘。这种方法适合使用脚本或功能简单的自研平台创建虚拟机的情况。
Cloudbase-init的方法暂且不表,本文先演示笔者管理的环境里如何初始化Windows虚拟机的网络配置。
操作环境
宿主机操作系统CentOS7.4
虚拟机操作系统 Windows Server 2012 r2
虚拟机拥有1块网卡,我们的试验任务就是让内置脚本为这块网卡配置制定的IP。
制作虚拟机镜像
首先使用Windows Server 2012 r2的光盘ISO文件安装一台虚拟机,然后进行以下步骤:
1. 约定数据格式
文件名约定为nicinfo.ini,后续我们编写的内置脚本将读取该文件,内容格式如下:
ipsetup:1 ip:192.168.1.2 mask:255.255.255.0 gw:192.168.1.1 mac: 52:54:00:a0:d8:67 |
各字段意义:
ipsetup是一个标志位,控制是否进行IP配置,1表示进行,0表示不进行。因为对虚拟机来说只有第一次启动时需要配置IP,其他时间的重启都不需要,所以内置脚本需要在完成IP配置后把ipsetup置0,防止脚本再次执行;
ip、mask、gw和mac分别是IP地址,网络掩码,网关和MAC地址。
2. 编写powershell脚本
脚本名setup.ps1,可以读取并解析符合上一步中所定义格式的数据,放在路径C:\Windows\下
sleep 120 $ini = Get-Content "C:\Windows\nicinfo.ini" $hash = @{} foreach ($iniLine in $ini) { $key = $iniLine.split(':',2)[0] $value = $iniLine.split(":",2)[1] $hash."$key" = $value } $ipsetup=$hash["ipsetup"]
if($ipsetup -eq "1"){ $ip = $hash["ip"] $mask = $hash["mask"] $gw = $hash["gw"] $mac = $hash["mac"] $nic = Get-WmiObject win32_networkadapterconfiguration -filter "MACAddress='$mac'" $nic.EnableStatic($ip, $mask) $nic.SetGateways($gw, 1) $nic.SetDNSServerSearchOrder("8.8.8.8") $ini -replace "ipsetup:1","ipsetup:0" > tmp.ini mv -Force tmp.ini nicinfo.ini } |
开始让脚本sleep 120秒是给网卡设备启用时间,如果不等待,有可能会出现脚本在网卡起来之前就运行,导致配置IP失败。
如果ipsetup值为1,脚本就按照给定的数据设置网卡信息,并在结尾把ipsetup置0 。
3. 添加脚本开机启动
在“运行”中执行gpedit.msc,进入组策略管理,找到计算机配置->Windows设置->脚本(启动/关机),双击“启动”按钮
切换到powershell标签,点击“添加”:
添加上一步中写的脚本,然后点击确定,就添加完成了。
设置完后把虚拟机关机,现在这个镜像就可以拿来创建新的虚拟机了。
验证
在宿主机上执行以下命令:
virt-copy-in -a vmdisk.img nicinfo.ini C:/Windows/ |
vmdisk.img是刚才制作好的虚拟机镜像文件。
然后把虚拟机开机,过一会登录虚拟机会发现网卡已经配置好了,