Cloud.ps1

<#
$ sudo apt install -y genisoimage
 
#>


function New-CloudInit {
  param(
    [Parameter(mandatory = $true)]
    [string] $Path,
    [Parameter(mandatory = $true)]
    [string] $Hostname,
    [Parameter(mandatory = $true)]
    [string] $Address
  )

  if (-not(Test-Path -Path $path -PathType Container)) {
    New-Item -Path $path -ItemType Directory | Out-Null
  }

  $seedImg = Join-Path $Path "seed.img"
  $metadata = Join-Path $Path "meta-data"
  $userdata = Join-Path $Path "user-data"

  "local-hostname: ${Hostname}" | Out-File -FilePath $metadata

  @"
#cloud-config
users:
  - name: box
    groups: sudo, docker
    sudo: ["ALL=(ALL) NOPASSWD:ALL"]
    plain_text_passwd: password
    lock_passwd: false
    shell: /bin/bash
    #ssh_pwauth: true
    ssh_authorized_keys:
      - $(Get-Content (Get-SshKey -Public))
   
# package_update: false
   
bootcmd:
   
  #
  - echo "blacklist floppy" > /etc/modprobe.d/blacklist-floppy.conf
  - rmmod floppy
  - update-initramfs -u
   
  # Ubuntu cloud ova comes with its own netplan config for enp0s3
  - printf "network:\n ethernets:\n enp0s8:\n addresses:\n - ${Address}\n" > /etc/netplan/60-host-only.yaml
  - netplan apply
   
  # Disable snapd
  - systemctl disable snapd
  - systemctl mask snapd
   
runcmd:
  - touch /etc/cloud/cloud-init.disabled
"@
 | Out-File -FilePath $userdata
  

  # https://blog.idera.com/database-tools/powershell/powertips/creating-iso-files/
  # https://thedotsource.com/2021/03/16/building-iso-files-with-powershell-7/
  # https://gitlab.com/xtec/box/-/tree/207febefe8500f17d847ef44aff9c3d5bc145b3d/cloud-init

  #$image = New-Object -ComObject IMAPI2FS.MsftFileSystemImage
  #$image.VolumeName = "cidata"
  # create CDROM, Joliet and UDF file systems
  #$image.FileSystemsToCreate = 7
  
  New-SeedImg -File $seedImg -MetaData $metadata -UserData $userdata
  
  Remove-Item $metadata, $userdata

  return $seedImg
}

# No funciona, necessitem rock ridge compatible
function New-SeedImg {
  param(
    [string] $File,
    [string] $MetaData,
    [string] $UserData
  )

  ## Set type definition

  $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();
          }
      }
  }
'@


  ## Create type ISOFile, if not already created. Different actions depending on PowerShell version
  if (!('ISOFile' -as [type])) {

    ## Add-Type works a little differently depending on PowerShell version.
    ## https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/add-type
    switch ($PSVersionTable.PSVersion.Major) {

      ## 7 and (hopefully) later versions
      { $_ -ge 7 } {
        Write-Verbose ("Adding type for PowerShell 7 or later.")
        Add-Type -CompilerOptions "/unsafe" -TypeDefinition $typeDefinition
      }

      ## 5, and only 5. We aren't interested in previous versions.
      5 {
        Write-Verbose ("Adding type for PowerShell 5.")
        $compOpts = New-Object System.CodeDom.Compiler.CompilerParameters
        $compOpts.CompilerOptions = "/unsafe"

        Add-Type -CompilerParameters $compOpts -TypeDefinition $typeDefinition
      }

      default {
        ## If it's not 7 or later, and it's not 5, then we aren't doing it.
        throw ("Unsupported PowerShell version.")

      }
    }
  }

  ## Build array of media types
  $mediaType = @(
    "UNKNOWN",
    "CDROM",
    "CDR",
    "CDRW",
    "DVDROM",
    "DVDRAM",
    "DVDPLUSR",
    "DVDPLUSRW",
    "DVDPLUSR_DUALLAYER",
    "DVDDASHR",
    "DVDDASHRW",
    "DVDDASHR_DUALLAYER",
    "DISK",
    "DVDPLUSRW_DUALLAYER",
    "HDDVDROM",
    "HDDVDR",
    "HDDVDRAM",
    "BDROM",
    "BDR",
    "BDRE"
  )

  ## Initialise image

  $image = New-Object -ComObject IMAPI2FS.MsftFileSystemImage -Property @{VolumeName = 'cidata' } -ErrorAction Stop
  $image.VolumeName = "cidata"
  $image.ChooseImageDefaultsForMediaType($mediaType.IndexOf(1))
  # create CDROM, Joliet and UDF file systems
  $image.FileSystemsToCreate = 7

  $image | Get-Member | Out-Host
  
  $image.Root.AddTree($MetaData, $true)
  $image.Root.AddTree($UserData, $true)

  $result = $image.CreateResultImage()
  [ISOFile]::Create($File, $result.ImageStream, $result.BlockSize, $result.TotalBlocks)
}