简体   繁体   中英

Sysprep an Azure VM using PowerShell task in a pipeline

My (dotNET) application is built (using a Windows Hosted agent), from a build pipeline, and in the subsequent Release pipeline, I provision a 16GB-Win2016 VM (enabling RDP, HTTP, HTTPS, WinRM and SSH), into which I RDP manually (there is a Manual Intervention task here), and configure WinRM (following this article: https://docs.microsoft.com/en-us/azure/marketplace/cloud-partner-portal/virtual-machine/cpp-configure-winrm-after-vm-creation#configure-vm-to-enable-winrm ). Everything is fine until here. The next task is a Azure File Copy task, which essentially copies the Build artifacts (from $(System.DefaultWorkingDirectory) ) and pastes into a directory I specify. Works like a charm. The next task I have is to create a VHD of this whole VM (essentially after the copying is done).

I know I can manually RDP into the VM (again) and sysprep (with oobe/generalize/shutdown), then maybe go back to the Azure Portal and Disk Export the OS Disk (specifying the SAS URL expiration time at whatever (36000 per the article)) BUT can this all be automated?

So, long story short - I'd like to know if sysprep oobe/generalize/shutdown can be performed remotely preferably over a PS task. I understand the other part of it (exporting the disk and all) can be, but if sysprep can be done remotely nothing like it.

I tried this and got what I wanted:

$sysprep= 'C:\Windows\System32\Sysprep\Sysprep.exe'
$arg1 = '/generalize'
$arg2 = '/oobe'
$arg3 = '/shutdown'
$arg4 = '/quiet'

& $sysprep $arg1 $arg2 $arg3 $arg4 -Wait

Make sure you do NOT use Azure custom script extension to run sysprep.

Azure scripts run under the LocalSystem user context: source

Custom Script Extension will run under the LocalSystem Account

This is problematic because sysprep does NOT support running under a system user context: source

Sysprep cannot be run under the context of a System account. Running Sysprep under the context of System account by using Task Scheduler or PSExec, for example, is not supported.

Providing this so that people avoid my mistake :)

So, you dont have to configure winrm manually, you can script it\\configure it while provisioning the vm. and if\\when winrm is working you can just use powershell remoting to issue a command against the vm with:

Invoke-Command -ComputerName dnsname\ipaddress_goes_hehe
    -ScriptBlock { sysprep /shutdown /generalise}

https://github.com/Azure/azure-quickstart-templates/tree/master/201-vm-winrm-windows

You can implement this using an Azure custom script extension. There is a github project: https://github.com/jlongo62/AzureVMToImage containing powershell scripts to image a VM. These scripts were built to preserve VM when creating an image, instead of destroying the original VM. The scripts can be called from Azure Devops. There is no need to authenticate against the VM.

The meat of what you need is:

1- create a storageaccount blob containing the following script (the -Wait is very important):

Start-Process -FilePath C:\Windows\System32\Sysprep\Sysprep.exe -ArgumentList '/generalize /oobe /quiet /quit'  -Wait 

2 - invoke it on the VM:

$response = Set-AzureRmVMCustomScriptExtension  `
                -ResourceGroupName  $vm.ResourceGroupName `
                -VMName $vm.Name `
                -Location $vm.Location `
                -Name $ExtensionName  `
                -FileUri $blobUri  `
                -Run $FileName 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM