はじめに
IBM CloudにおけるVSI for VPCのWindows環境では、cloudbase-initを利用した初期化設定を行なっている。
その設定内容などを確認してみた。
参考docs: https://cloud.ibm.com/docs/vpc?topic=vpc-create-windows-custom-image
Windows Serverのイメージの作成と起動の流れ
1. Unattend.xml を指定して Sysprep を実行(Sysprepの generalize フェーズ)。
Windows の SID や固有情報がリセットされ、配布用の汎用イメージに変換される。
↓
2. サーバーをシャットダウン。
↓
--- 初回初期化起動 ---
3. Sysprepの specialize フェーズ
初回ブート直後に実行され、Windows が新しい環境(ハードウェア、ネットワークなど)へ適応するフェーズ。
このタイミングで cloudbase-init-unattend.conf を元に cloudbase-init が実行される。
↓
4. Sysprepの oobe フェーズ
Windows の初回起動時に実行される Out-Of-Box Experience(セットアップ画面)に相当するフェーズ。
↓
--- 通常起動(2回目起動も含む) ---
5. Windows が通常起動し、cloudbase-init.conf を元に cloudbase-init が実行される。
VSI for VPC上に配置されていたSysprep用設定ファイル(Unattend.xml, cloudbase-init-unattend.conf)
-
Unattend.xml: sysprepコマンド実行時に指定するファイル。Sysprep の各フェーズ(特に / oobe)を制御する Windows 標準の XML。 -
cloudbase-init-unattend.conf: sysprep 実行のタイミングで cloudbase-init が使う設定ファイル(Unattend.xml内で指定されている)。specialize フェーズで Cloudbase-Init を初期実行するときに読む専用の設定
C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="generalize">
<component name="Microsoft-Windows-PnpSysprep" 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">
<PersistAllDeviceInstalls>false</PersistAllDeviceInstalls>
</component>
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<OOBE>
<HideEULAPage>true</HideEULAPage>
<NetworkLocation>Work</NetworkLocation>
<ProtectYourPC>1</ProtectYourPC>
<SkipMachineOOBE>true</SkipMachineOOBE>
<SkipUserOOBE>true</SkipUserOOBE>
</OOBE>
</component>
</settings>
<settings pass="specialize">
<component name="Microsoft-Windows-Deployment" 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">
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>cmd.exe /c ""C:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\Scripts\cloudbase-init.exe" --config-file "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf" && exit 1 || exit 2"</Path>
<Description>Run Cloudbase-Init to set the hostname</Description>
<WillReboot>OnRequest</WillReboot>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
</unattend>
C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf
[DEFAULT]
# "cloudbase-init-unattend.conf" is used during the Sysprep phase
username=Administrator
inject_user_password=true
first_logon_behaviour=no
config_drive_types=vfat,iso
config_drive_locations=hdd,partition
allow_reboot=false
stop_service_on_exit=false
mtu_use_dhcp_config=false
ntp_use_dhcp_config=true
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
debug=true
log_dir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\
log_file=cloudbase-init-unattend.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN
local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\
metadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService
# enabled plugins - executed in order
plugins=cloudbaseinit.plugins.common.mtu.MTUPlugin,
cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin,
cloudbaseinit.plugins.windows.createuser.CreateUserPlugin,
cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin,
cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin,
cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin
VSI for VPC上に配置されていたcloudbase-init用設定ファイル(cloudbase-init.conf)
C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init.conf
[DEFAULT]
# "cloudbase-init.conf" is used for every boot
config_drive_types=vfat,iso
config_drive_locations=hdd,partition
activate_windows=true
kms_host=kms.adn.networklayer.com:1688
mtu_use_dhcp_config=false
ntp_use_dhcp_config=true
real_time_clock_utc=false
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
debug=true
log_dir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\
log_file=cloudbase-init.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN
metadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService
# enabled plugins - executed in order
plugins=cloudbaseinit.plugins.common.mtu.MTUPlugin,
cloudbaseinit.plugins.windows.ntpclient.NTPClientPlugin,
cloudbaseinit.plugins.windows.licensing.WindowsLicensingPlugin,
cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin,
cloudbaseinit.plugins.common.userdata.UserDataPlugin
- ConfigDriveServiceを使って(VSI for VPCのLinux版と同様に)プロビジョニング時に払い出されるDISKからメタデータを取得していることがわかる。
- Bring Your Own Licenseを利用したい場合は以下を削除する。
- activate_windows=true
- kms_host=kms.adn.networklayer.com:1688
cloudbase-initが読み込むメタ情報が含まれるDISKを確認する
ログによると、<Disk: \\.\PHYSICALDRIVE1>が使われていそう。
PS C:\> Select-String -Path "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log" -Pattern "disk", "user_data"
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:73:2025-12-22 07:25:19.468 4696 WARNING
cloudbaseinit.metadata.services.osconfigdrive.windows [-] ISO extraction failed on <Partition: \\?\GLOBALROOT\Device\Harddisk0\Partition2> with
WindowsCloudbaseInitException("Cannot open file: 'The process cannot access the file because it is being used by another process.'",):
cloudbaseinit.exception.WindowsCloudbaseInitException: Cannot open file: 'The process cannot access the file because it is being used by another process.'
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:74:2025-12-22 07:25:19.485 4696 WARNING
cloudbaseinit.metadata.services.osconfigdrive.windows [-] ISO extraction failed on <Partition: \\?\GLOBALROOT\Device\Harddisk0\Partition3> with
WindowsCloudbaseInitException("Cannot open file: 'The process cannot access the file because it is being used by another process.'",):
cloudbaseinit.exception.WindowsCloudbaseInitException: Cannot open file: 'The process cannot access the file because it is being used by another process.'
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:76:2025-12-22 07:25:19.577 4696 INFO
cloudbaseinit.metadata.services.osconfigdrive.windows [-] ISO9660 disk found on <Disk: \\.\PHYSICALDRIVE1>
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:178:2025-12-22 07:25:35.552 4696 DEBUG cloudbaseinit.plugins.common.userdata [-]
Processing userdata _process_user_data C:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\lib\site-packages\cloudbaseinit\plugins\common\userdata.py:109
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:221:2025-12-22 07:25:46.927 4696 DEBUG cloudbaseinit.plugins.common.fileexecutils [-]
User_data stdout:
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:223:2025-12-22 07:25:46.927 4696 DEBUG cloudbaseinit.plugins.common.fileexecutils [-]
User_data stderr:
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:228:2025-12-22 07:25:49.140 4696 DEBUG cloudbaseinit.plugins.common.fileexecutils [-]
User_data stdout:
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:230:2025-12-22 07:25:49.140 4696 DEBUG cloudbaseinit.plugins.common.fileexecutils [-]
User_data stderr:
(以下略)
<Disk: \\.\PHYSICALDRIVE1> の中身を確認する
PS C:\> Get-CimInstance Win32_DiskDrive | Sort
DeviceID Caption Partitions Size Model
-------- ------- ---------- ---- -----
\\.\PHYSICALDRIVE0 QEMU QEMU HARDDISK SCSI Disk Device 4 107372805120 QEMU QEMU HARDDISK SCSI Disk Device
\\.\PHYSICALDRIVE1 QEMU QEMU HARDDISK SCSI Disk Device 0 387072 QEMU QEMU HARDDISK SCSI Disk Device
\\.\PHYSICALDRIVE2 Red Hat VirtIO SCSI Disk Device 0 45056 Red Hat VirtIO SCSI Disk Device
以下のスクリプトを実行
$src = "\\.\PHYSICALDRIVE1"
$dst = "C:\configdrive.iso"
# PHYSICALDRIVE1 のサイズを取得
$disk = Get-CimInstance Win32_DiskDrive | Where-Object DeviceID -eq $src
$size = [int64]$disk.Size
$in = [System.IO.File]::Open($src, 'Open', 'Read', 'ReadWrite')
$out = [System.IO.File]::Create($dst)
$bufferSize = 64KB
$buffer = New-Object byte[] $bufferSize
$remaining = $size
while ($remaining -gt 0) {
$toRead = [Math]::Min($bufferSize, $remaining)
$read = $in.Read($buffer, 0, $toRead)
if ($read -le 0) { break }
$out.Write($buffer, 0, $read)
$remaining -= $read
}
$in.Close()
$out.Close()
Write-Host "Copy completed: $dst"
上記で作成されたisoをマウントすると、
meta_data.json
{"hostname":"syasuda-win01","name":"syasuda-win01","uuid":"xxxx_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-xxxxx","admin_pass":""}
network_data.json
{}
user_data
Content-Type: multipart/mixed; boundary=c70c0bce2cb7bc7ddc1c02162b7eb2c4fbbced4a42cbe8e0e9c98103afe3
MIME-Version: 1.0
--c70c0bce2cb7bc7ddc1c02162b7eb2c4fbbced4a42cbe8e0e9c98103afe3
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="enable-rdp.ps1"
#ps1_sysnative
function enable-rdp () {
Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\' -Name fDenyTSConnections -Value 0
Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\' -Name 'UserAuthentication' -Value 1
Enable-NetFireWallRule -DisplayGroup 'Remote Desktop'
}
enable-rdp
--c70c0bce2cb7bc7ddc1c02162b7eb2c4fbbced4a42cbe8e0e9c98103afe3
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="enable-ping.ps1"
#ps1_sysnative
function enable-ping () {
Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True
Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True
}
enable-ping
--c70c0bce2cb7bc7ddc1c02162b7eb2c4fbbced4a42cbe8e0e9c98103afe3--
vendor_data.json
{}


