新创建的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是刚才制作好的虚拟机镜像文件。

然后把虚拟机开机,过一会登录虚拟机会发现网卡已经配置好了,