Coder Social home page Coder Social logo

hyperv-vm-provisioning's Introduction

Powershell scripts for fast Linux VM provisioning

Features

  • Provision Linux VM using cloud-init on Hyper-V in a single command
  • Use custom userdata yaml, see examples
  • Using Ubuntu Cloud Images certified for Azure and proven to work reliably on Hyper-V (22.04 jammy, 20.04 focal, 18.04 bionic) with tailored Microsoft kernel included
  • Generation 1 for Azure migration friendliness or Generation 2 Hyper-V virtual machine type supported
  • Automatic update check for a newer image on provisioning
  • Works on Windows 10 and Hyper-V 2016

Example usage

.\New-HyperVCloudImageVM.ps1 -VMProcessorCount 2 -VMMemoryStartupBytes 2GB -VHDSizeBytes 60GB -VMName "ubuntu-1" -ImageVersion "22.04" -VMGeneration 2 -ShowSerialConsoleWindow

Parameter ImageVersion accepts the following values:

  • Ubuntu: "18.04", "20.04", "22.04", "22.04-azure"
  • Debian: "10", "11"

Remark/Disclaimer: Azure image types by default supports DataSourceAzure cloud-init type which expects Azure environment. Since we are not emulating Azure cloud-init environment the only way to use those images is to converting those images to NoCloud datasource - this requires at least Windows 11 build 22000 because it uses wsl --mount (see wsl-convert-vhd-nocloud.cmd).

Default username is admin and password is Passw0rd (easily overriden with script parameters). Use standard parameters as needed: unattended use -Force, get some additional details -Verbose or to make initial checkpoint for VM use -Debug.

You should provide your own custom userdata.yaml as script parameter and customize the final image.

Download

One line powershell command

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; $r='hyperv-vm-provisioning'; iwr -Uri 'https://github.com/schtritoff/hyperv-vm-provisioning/archive/master.zip' -UseBasicParsing -OutFile "$r.zip" ; Expand-Archive "$r.zip" -Force ; Remove-Item "$r.zip" -Force

Troubleshooting

If you get error ERROR Daemon /proc/net/route contains no routes on serial console then you need to check if your VM has got and IP address - that is requirement for provisioning to work properly. You need to reboot VM after adding IP to finish with provisioning.

Similar projects and credits

https://blogs.msdn.microsoft.com/virtual_pc_guy/2015/06/23/building-a-daily-ubuntu-image-for-hyper-v/

https://github.com/MicrosoftDocs/Virtualization-Documentation/blob/master/hyperv-samples/benarm-powershell/Ubuntu-VM-Build/BaseUbuntuBuild.ps1

https://github.com/fdcastel/Hyper-V-Automation/blob/master/New-VMFromUbuntuImage.ps1

https://gist.github.com/PulseBright/3a6fe586821a2ff84cd494eb897d3813

https://gist.github.com/matrey/66d697ef540f0da8933a341524ea9fd7

https://matrey.github.io/articles/build-your-own-ubuntu-ami/

License

public domain or any other license for reused work from original authors

hyperv-vm-provisioning's People

Contributors

didlich avatar gabloe avatar kennhung avatar kosmolito avatar levytskyip avatar reiner030 avatar schtritoff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

hyperv-vm-provisioning's Issues

Serial console - Named pipe

Hi,

During my quest to streamline our Linux machine setups I came across your amazing script and love it!

Are you able to get the serial console output to a named pipe? I tried and it just doesn't work, and based on the documentation from Microsoft here it seems the named pipe must already exist in order for HyperV to be able to use it, which adds up as I checked use pipelist and I didn't see the named pipe used.

Regards,

Automate Static IP

Script is working well
What are the steps to have the VM use a static IP
New-HyperVCloudImageVM would need to be updated or i need to pass some variables to script
Can't work it out
Trying this an ubuntu vm
Thanks

Automate Static IP (Ubuntu)

Static IP for Debian build is working fine.
If I select image version as 22.04, it comes up with an error, but continues to build the vm with a dhcp setting.
Error : "WARNING: No Network Configuration version type defined for static IP address setup"
If I add a variable : "$NetConfigType=v1" , I get no errors, but the static IP is not applied. Neither is the username/password

Command I am using is :
./New-HyperVCloudImageVM.ps1 -VMProcessorCount 2 -VMMemoryStartupBytes 2GB -VHDSizeBytes 8GB -VMName Ubuntu -ImageVersion "22.04" -virtualSwitchName "Home" -VMGeneration 2 -GuestAdminUsername admin -GuestAdminPassword password -VMMachine_StoragePath "D:\VM" -NetAddress 192.168.10.10 -NetNetmask 255.255.255.0 -NetGateway 192.168.10.1 -NameServers 8.8.8.8 -NetConfigType "v1"

Which setting for this variable should it be for Ubuntu builds ? I can't get either to work
Does it require more info ?

Switch to full PowerShell for ISO creation

I'm sorry that I'm doing this as an issue instead of a PR I'm just too lazy for a full PR but I still want to give this (hopefully) helpful code.

The below code creates an ISO completely in PowerShell, without relying on external software dependencies. I found this a while back floating around on the internet, and crudely modified it to make it work for cloud-init, you might appreciate to use this instead of relying on oscdimg.

function New-IsoFile  {  
<#  
    .Synopsis  
    Creates a new .iso file  
    .Description  
    The New-IsoFile cmdlet creates a new .iso file containing content from chosen folders  
    .Example  
    New-IsoFile "c:\tools","c:Downloads\utils"  
    This command creates a .iso file in $env:temp folder (default location) that contains c:\tools and c:\downloads\utils folders. The folders themselves are included at the root of the .iso image.  
    .Example 
    New-IsoFile -FromClipboard -Verbose 
    Before running this command, select and copy (Ctrl-C) files/folders in Explorer first.  
    .Example  
    dir c:\WinPE | New-IsoFile -Path c:\temp\WinPE.iso -BootFile "${env:ProgramFiles(x86)}\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\efisys.bin" -Media DVDPLUSR -Title "WinPE" 
    This command creates a bootable .iso file containing the content from c:\WinPE folder, but the folder itself isn't included. Boot file etfsboot.com can be found in Windows ADK. Refer to IMAPI_MEDIA_PHYSICAL_TYPE enumeration for possible media types: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366217(v=vs.85).aspx  
    .Notes 
    NAME:  `
    AUTHOR: Chris Wu 
    LASTEDIT: 03/23/2016 14:46:50  
#>  

    [CmdletBinding(DefaultParameterSetName='Source')]Param( 
        [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source,  
        [parameter(Position=2)][string]$Path = "$env:temp\$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso",  
        [ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null, 
        [ValidateSet('CDR','CDRW','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','BDR','BDRE')][string] $Media = 'DVDPLUSRW_DUALLAYER', 
        [string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"),  
        [switch]$Force, 
        [parameter(ParameterSetName='Clipboard')][switch]$FromClipboard 
    )

    Begin {  
        ($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe' 
        if (!('ISOFile' -as [type])) {  
        Add-Type -CompilerParameters $cp -TypeDefinition @' 
public class ISOFile  
{ 
public unsafe static void Create(string Path, object Stream, int BlockSize, int TotalBlocks)  
{  
    int bytes = 0;  
    byte[] buf = new byte[BlockSize];  
    var ptr = (System.IntPtr)(&bytes);  
    var o = System.IO.File.OpenWrite(Path);  
    var i = Stream as System.Runtime.InteropServices.ComTypes.IStream;  

    if (o != null) { 
    while (TotalBlocks-- > 0) {  
        i.Read(buf, BlockSize, ptr); o.Write(buf, 0, bytes);  
    }  
    o.Flush(); o.Close();  
    } 
} 
}  
'@  
        } 

        if ($BootFile) { 
        if('BDR','BDRE' -contains $Media) { Write-Warning "Bootable image doesn't seem to work with media type $Media" } 
        ($Stream = New-Object -ComObject ADODB.Stream -Property @{Type=1}).Open()  # adFileTypeBinary 
        $Stream.LoadFromFile((Get-Item -LiteralPath $BootFile).Fullname) 
        ($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream) 
        } 

        $MediaType = @('UNKNOWN','CDROM','CDR','CDRW','DVDROM','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','HDDVDROM','HDDVDR','HDDVDRAM','BDROM','BDR','BDRE') 

        Write-Verbose -Message "Selected media type is $Media with value $($MediaType.IndexOf($Media))" 
        ($Image = New-Object -com IMAPI2FS.MsftFileSystemImage -Property @{VolumeName=$Title}).ChooseImageDefaultsForMediaType($MediaType.IndexOf($Media)) 

        if (!($Target = New-Item -Path $Path -ItemType File -Force:$Force -ErrorAction SilentlyContinue)) { Write-Error -Message "Cannot create file $Path. Use -Force parameter to overwrite if the target file already exists."; break } 
    }  

    Process { 
        if($FromClipboard) { 
            if($PSVersionTable.PSVersion.Major -lt 5) { Write-Error -Message 'The -FromClipboard parameter is only supported on PowerShell v5 or higher'; break } 
            $Source = Get-Clipboard -Format FileDropList 
        } 

        foreach($sitem in $Source) { 
            if($sitem -isnot [System.IO.FileInfo] -and $item -isnot [System.IO.DirectoryInfo]) { 
                $sitems = Get-childItem -LiteralPath $sitem 
            } 
            foreach ($item in $sitems) {
                if($item) { 
                    Write-Verbose -Message "Adding item to the target image: $($item.FullName)" 
                    try { $Image.Root.AddTree($item.FullName, $true) } catch { Write-Error -Message ($_.Exception.Message.Trim() + ' Try a different media type.') } 
                } 
            }

        } 
    } 

    End {  
        if ($Boot) { $Image.BootImageOptions=$Boot }
            $image.FileSystemsToCreate = 3
            $Image.ISO9660InterchangeLevel = 2
            $Image.GetDefaultFileSystemForImport(1)
            $Image.UseRestrictedCharacterSet = $true
            $Result = $Image.CreateResultImage()
            [ISOFile]::Create($Target.FullName,$Result.ImageStream,$Result.BlockSize,$Result.TotalBlocks)
            Write-Verbose -Message "Target image ($($Target.FullName)) has been created"
            $Target
    } 
}

I did some changes to common version floating around, namely I hardcoded in that the ISO should specifically use the ISO9660 filesystem and not UDF as per the documentation this is required. The actual changes are $image.FileSystemsToCreate = 3 (link) and $Image.GetDefaultFileSystemForImport(1) (link) I did some other minor changes but those most probably aren't really needed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.