commit 02907e7c6505ad45c57ce25d3062753867e54554 Author: djpbessems Date: Sat Jan 23 15:59:06 2021 +0100 Delete commit history (containing proprietary code) diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..8b13cc4 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,64 @@ +kind: pipeline +type: kubernetes +name: 'Packer Build' + +steps: +- name: Windows Server 2019 + image: bv11-cr01.bessems.eu/library/packer-extended + commands: + - sed -i -e "s/<>/$${PRODUCTKEY}/" packer/preseed/Server2019/Autounattend.xml + - | + sed -i -e "s/<>/$${WINRM_PASSWORD}/g" \ + packer/preseed/Server2019/Autounattend.xml \ + packer/preseed/Server2019/Sysprep_Unattend.xml + - | + packer validate \ + -var-file=packer/variables.vsphere.json \ + -var vm_name=$DRONE_BUILD_NUMBER-${DRONE_COMMIT_SHA:0:10} \ + -var vm_guestos=server2019 \ + -var repo_username=$${REPO_USERNAME} \ + -var repo_password=$${REPO_PASSWORD} \ + -var vsphere_password=$${VSPHERE_PASSWORD} \ + -var winrm_password=$${WINRM_PASSWORD} \ + packer/windowsserver2019.json + - | + packer build \ + -on-error=cleanup \ + -var-file=packer/variables.vsphere.json \ + -var vm_name=$DRONE_BUILD_NUMBER-${DRONE_COMMIT_SHA:0:10} \ + -var vm_guestos=server2019 \ + -var repo_username=$${REPO_USERNAME} \ + -var repo_password=$${REPO_PASSWORD} \ + -var vsphere_password=$${VSPHERE_PASSWORD} \ + -var winrm_password=$${WINRM_PASSWORD} \ + packer/windowsserver2019.json + environment: + VSPHERE_PASSWORD: + from_secret: vsphere_password + WINRM_PASSWORD: + from_secret: winrm_password + REPO_USERNAME: + from_secret: repo_username + REPO_PASSWORD: + from_secret: repo_password + PRODUCTKEY: + from_secret: prodkey_server2019 + # PACKER_LOG: 1 + volumes: + - name: output + path: /output +- name: Trigger downstream builds + image: plugins/downstream + settings: + server: https://ci.spamasaurus.com + token: + from_secret: drone_token + fork: true + repositories: + - djpbessems/Packer.Images@ADCS + - djpbessems/Packer.Images@ADDS + +volumes: +- name: output + claim: + name: flexvolsmb-drone-output \ No newline at end of file diff --git a/.drone.yml.backup b/.drone.yml.backup new file mode 100644 index 0000000..50ecca3 --- /dev/null +++ b/.drone.yml.backup @@ -0,0 +1,16 @@ + +# Convert to WIM: +# tasks: +# scripts: +# # Download .vmdk +# - ${bamboo.build.working.directory}\bamboo-specs\scripts\Copy-DatastoreItem.ps1 -VMName ${bamboo.vmname}-physical -VSpherePassword "${bamboo.vspherepassword}" +# # Remove unsupported key from descriptor file +# - Set-Content -Path "${bamboo.vmname}-physical.vmdk" -Value (Get-Content -Path "${bamboo.vmname}-physical.vmdk" | Select-String -Pattern 'ddb\.toolsInstallType.*' -NotMatch) +# # Convert to .vhd +# - Import-Module ${bamboo.build.working.directory}\bamboo-specs\scripts\MVMC\MvmcCmdlet.psd1 +# - ConvertTo-MvmcVirtualHardDisk -SourceLiteralPath "${bamboo.vmname}-physical.vmdk" -DestinationLiteralPath "${bamboo.vmname}-physical.vhd" -VhdType DynamicHardDisk -VhdFormat Vhd +# - Remove-Item *.vmdk +# # Convert to .wim +# - $MountPath = New-Item -Path "$PWD\Mount" -ItemType 'Directory' -Force +# - Mount-WindowsImage -ImagePath "${bamboo.vmname}-physical.vhd" -Path $MountPath.FullName -Index 1 +# - ${bamboo.build.working.directory}\bamboo-specs\scripts\New-WindowsImageJob.ps1 -ImageName 'Server2019' -SourceFolder $MountPath.FullName -DestinationFile "$PWD\diskimage.wim" diff --git a/README.md b/README.md new file mode 100644 index 0000000..198852d --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Packer.Images [![Build Status](https://ci.spamasaurus.com/api/badges/djpbessems/Packer.Images/status.svg)](https://ci.spamasaurus.com/djpbessems/Packer.Images) + diff --git a/packer/preseed/Server2019/Autounattend.xml b/packer/preseed/Server2019/Autounattend.xml new file mode 100644 index 0000000..24e9e51 --- /dev/null +++ b/packer/preseed/Server2019/Autounattend.xml @@ -0,0 +1,159 @@ + + + + + + + + + + 1 + Primary + true + + + + + false + NTFS + C + 1 + 1 + + + + 0 + true + + OnError + + + true + + + <> + Never + + + + + + 0 + 1 + + OnError + false + + + /IMAGE/INDEX + 4 + + + + + + + + en-US + + en-US + en-US + en-US + en-US + en-US + + + + + false + + + + + en-US + en-US + en-US + en-US + + + + + <> + true</PlainText> + </AdministratorPassword> + </UserAccounts> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> + <NetworkLocation>Home</NetworkLocation> + <ProtectYourPC>1</ProtectYourPC> + </OOBE> + <AutoLogon> + <Password> + <Value><<img-password>></Value> + <PlainText>true</PlainText> + </Password> + <Username>administrator</Username> + <Enabled>true</Enabled> + </AutoLogon> + <FirstLogonCommands> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <Description>Set execution policy 64bit</Description> + <Order>1</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>C:\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <Description>Set execution policy 32bit</Description> + <Order>2</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c reg add "HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff"</CommandLine> + <Description>Disable new network prompt</Description> + <Order>3</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\Set-NetworkProfile.ps1</CommandLine> + <Description>Set network profile to private</Description> + <Order>4</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\Disable-WinRM.ps1</CommandLine> + <Description>Disable WinRM</Description> + <Order>5</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c a:\Install-VMwareTools.cmd</CommandLine> + <Order>13</Order> + <Description>Install VMware Tools</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\Enable-WinRM.ps1</CommandLine> + <Description>Enable WinRM</Description> + <Order>99</Order> + </SynchronousCommand> + </FirstLogonCommands> + <ShowWindowsLive>false</ShowWindowsLive> + </component> + </settings> + <settings pass="specialize"> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> + <OEMInformation> + <HelpCustomized>false</HelpCustomized> + </OEMInformation> + <!-- Rename computer here. --> + <ComputerName>packer-template</ComputerName> + <TimeZone>W. Europe Standard Time</TimeZone> + <RegisteredOwner/> + </component> + <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> + <SkipAutoActivation>true</SkipAutoActivation> + </component> + </settings> +</unattend> diff --git a/packer/preseed/Server2019/Sysprep_Unattend.xml b/packer/preseed/Server2019/Sysprep_Unattend.xml new file mode 100644 index 0000000..fc79fe6 --- /dev/null +++ b/packer/preseed/Server2019/Sysprep_Unattend.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<unattend xmlns="urn:schemas-microsoft-com:unattend"> + <settings pass="generalize"> + <component name="Microsoft-Windows-Security-SPP" 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"> + <SkipRearm>1</SkipRearm> + </component> + <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>true</PersistAllDeviceInstalls> + <DoNotCleanUpNonPresentDevices>true</DoNotCleanUpNonPresentDevices> + </component> + </settings> + <settings pass="oobeSystem"> + <component name="Microsoft-Windows-International-Core" 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"> + <InputLocale>en-US</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UserLocale>en-US</UserLocale> + </component> + <component name="Microsoft-Windows-Shell-Setup" 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"> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <HideLocalAccountScreen>true</HideLocalAccountScreen> + <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> + <HideOnlineAccountScreens>true</HideOnlineAccountScreens> + <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> + <NetworkLocation>Work</NetworkLocation> + <ProtectYourPC>1</ProtectYourPC> + <SkipMachineOOBE>true</SkipMachineOOBE> + <SkipUserOOBE>true</SkipUserOOBE> + </OOBE> + <TimeZone>UTC</TimeZone> + <UserAccounts> + <AdministratorPassword> + <Value><<img-password>></Value> + <PlainText>true</PlainText> + </AdministratorPassword> + </UserAccounts> + </component> + </settings> + <settings pass="specialize"> + </settings> +</unattend> \ No newline at end of file diff --git a/packer/variables.vsphere.json b/packer/variables.vsphere.json new file mode 100644 index 0000000..cd6c507 --- /dev/null +++ b/packer/variables.vsphere.json @@ -0,0 +1,11 @@ +{ + "vcenter_server": "bv11-vc01.bessems.lan", + "vsphere_username": "administrator@vsphere.local", + "vsphere_datacenter": "DeSchakel", + "vsphere_host": "bv11-esx.bessems.eu", + "vsphere_hostip": "192.168.11.200", + "vsphere_datastore": "Datastore02.SSD", + "vsphere_folder": "/Packer", + "vsphere_templatefolder": "/Templates", + "vsphere_network": "LAN" +} \ No newline at end of file diff --git a/packer/windowsserver2019.json b/packer/windowsserver2019.json new file mode 100644 index 0000000..5b03a64 --- /dev/null +++ b/packer/windowsserver2019.json @@ -0,0 +1,154 @@ +{ + "builders": [ + { + "type": "vsphere-iso", + "name": "srv2019", + + "vcenter_server": "{{user `vcenter_server`}}", + "username": "{{user `vsphere_username`}}", + "password": "{{user `vsphere_password`}}", + "insecure_connection": "true", + + "vm_name": "{{user `vm_guestos`}}-{{user `vm_name`}}", + "datastore": "{{user `vsphere_datastore`}}", + "folder": "{{user `vsphere_folder`}}", + "datacenter": "{{user `vsphere_datacenter`}}", + "host": "{{user `vsphere_host`}}", + "boot_order": "disk,cdrom", + + "guest_os_type": "windows9Server64Guest", + + "communicator": "winrm", + "winrm_username": "administrator", + "winrm_password": "{{user `winrm_password`}}", + "winrm_timeout": "10m", + + "cpus": 2, + "RAM": 8192, + + "network_adapters": [ + { + "network": "{{user `vsphere_network`}}", + "network_card": "vmxnet3" + } + ], + "storage": [ + { + "disk_size": 20480, + "disk_thin_provisioned": true + } + ], + "disk_controller_type": "lsilogic-sas", + "usb_controller": "xhci", + + "iso_url": "https://{{user `repo_username`}}:{{user `repo_password`}}@sn.itch.fyi/Repository/iso/Microsoft/Windows%20Server%202019/LTSC/en_windows_server_2019_x64_dvd_4cb967d8.iso", + "iso_checksum": "sha256:4c5dd63efee50117986a2e38d4b3a3fbaf3c1c15e2e7ea1d23ef9d8af148dd2d", + "iso_paths": [ + "ISO-files/VMware-tools-windows-11.2.1-17243207/VMware-tools-windows-11.2.1-17243207.iso" + ], + "remove_cdrom": true, + + "floppy_files": [ + "packer/preseed/Server2019/Autounattend.xml", + "packer/preseed/Server2019/Sysprep_Unattend.xml", + "scripts/Set-NetworkProfile.ps1", + "scripts/Disable-WinRM.ps1", + "scripts/Enable-WinRM.ps1", + "scripts/Install-VMwareTools.cmd" + ], + + "boot_command": "", + "boot_wait": "5m", + + "shutdown_command": "C:\\Windows\\System32\\Sysprep\\sysprep.exe /generalize /oobe /unattend:A:\\Sysprep_Unattend.xml", + "shutdown_timeout": "1h", + + "export": { + "images": false + } + } + ], + "provisioners": [ + { + "type": "windows-update" + }, + { + "type": "powershell", + "inline": [ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12", + "Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" + ] + }, + { + "type": "powershell", + "inline": [ + "choco config set --name=limit-output --value=LimitOutput", + "choco install -y 7zip.install", + "choco install -y sysinternals" + ], + "valid_exit_codes": [0, 3010] + }, + { + "type": "windows-update" + }, + { + "type": "windows-restart", + "restart_check_command":"powershell -command \"& {Write-Output 'Probing restart status'}\"" + } + ], + "post-processors": [[ + { + "type": "vsphere", + "host": "{{user `vcenter_server`}}", + "username": "{{user `vsphere_username`}}", + "password": "{{user `vsphere_password`}}", + "insecure": true, + "vm_name": "Windows-Server-2019-LTSC", + "datacenter": "{{user `vsphere_datacenter`}}", + "cluster": "{{user `vsphere_host`}}", + "vm_folder": "{{user `vsphere_templatefolder`}}", + "datastore": "{{user `vsphere_datastore`}}", + "disk_mode": "thin", + "vm_network": "{{user `vsphere_network`}}", + "overwrite": true, + "keep_input_artifact": true + }, + { + "type": "vsphere-template", + "host": "{{user `vcenter_server`}}", + "username": "{{user `vsphere_username`}}", + "password": "{{user `vsphere_password`}}", + "insecure": true, + "datacenter": "{{user `vsphere_datacenter`}}", + "folder": "{{user `vsphere_templatefolder`}}", + "reregister_vm": false + } + ], + [ + { + "type": "shell-local", + "inline": [ + "pwsh -command \"& scripts/Update-OvfConfiguration.ps1 \\", + " -OVFFile './output-srv2019/{{user `vm_guestos`}}-{{user `vm_name`}}.ovf' \\", + " -Parameter @{'appliance.name'='{{user `vm_guestos`}}';'appliance.version'='{{user `vm_name`}}'}\"", + "pwsh -file scripts/Update-Manifest.ps1 \\", + " -ManifestFileName './output-srv2019/{{user `vm_guestos`}}-{{user `vm_name`}}.mf'", + "ovftool --acceptAllEulas --allowExtraConfig --overwrite \\", + " './output-srv2019/{{user `vm_guestos`}}-{{user `vm_name`}}.ovf' \\", + " /output/Windows-Server-2019-LTSC.ova" + ] + } + ], + [ + { + "type": "shell-local", + "inline": [ + "pwsh -file scripts/Remove-Resources.ps1 \\", + " -VMName '{{user `vm_guestos`}}-{{user `vm_name`}}' \\", + " -VSphereFQDN '{{user `vcenter_server`}}' \\", + " -VSphereUsername '{{user `vsphere_username`}}' \\", + " -VSpherePassword '{{user `vsphere_password`}}'" + ] + } + ]] +} diff --git a/packer/windowsserver2019.virt+phys.json b/packer/windowsserver2019.virt+phys.json new file mode 100644 index 0000000..35cab61 --- /dev/null +++ b/packer/windowsserver2019.virt+phys.json @@ -0,0 +1,201 @@ +{ + "builders": [ + { + "type": "vsphere-iso", + "name": "srv2019-virtual", + + "vcenter_server": "{{user `vcenter_server`}}", + "username": "{{user `vsphere_username`}}", + "password": "{{user `vsphere_password`}}", + "insecure_connection": "true", + + "vm_name": "{{user `vm_guestos`}}-{{user `vm_name`}}-virtual", + "datastore": "{{user `vsphere_datastore`}}", + "folder": "{{user `vsphere_folder`}}", + "datacenter": "{{user `vsphere_datacenter`}}", + "host": "{{user `vsphere_host`}}", + "boot_order": "disk,cdrom", + + "guest_os_type": "windows9Server64Guest", + + "communicator": "winrm", + "winrm_username": "administrator", + "winrm_password": "{{user `winrm_password`}}", + "winrm_timeout": "10m", + + "cpus": 2, + "RAM": 8192, + + "network_adapters": [ + { + "network": "{{user `vsphere_network`}}", + "network_card": "vmxnet3" + } + ], + "storage": [ + { + "disk_size": 20480, + "disk_thin_provisioned": true + } + ], + "disk_controller_type": "lsilogic-sas", + "usb_controller": "xhci", + + "iso_url": "https://{{user `repo_username`}}:{{user `repo_password`}}@sn.itch.fyi/Repository/iso/Microsoft/Windows%20Server%202019/LTSC/en_windows_server_2019_x64_dvd_4cb967d8.iso", + "iso_checksum": "sha256:4c5dd63efee50117986a2e38d4b3a3fbaf3c1c15e2e7ea1d23ef9d8af148dd2d", + "iso_paths": [ + "[Datastore01.NAS] contentlib-5c2187fa-55c5-4285-b06b-3f5f1ff9428d/e9342f62-6132-4044-bd42-48cab8c77034/VMware-tools-windows-11.2.1-17243207_4f88be10-b163-446b-ad7d-992e63b0e3ac.iso" + ], + + "floppy_files": [ + "packer/preseed/Server2019/Autounattend.xml", + "packer/preseed/Server2019/Sysprep_Unattend.xml", + "scripts/Set-NetworkProfile.ps1", + "scripts/Disable-WinRM.ps1", + "scripts/Enable-WinRM.ps1", + "scripts/Install-VMwareTools.cmd" + ], + + "boot_command": "", + "boot_wait": "5m", + + "shutdown_command": "C:\\Windows\\System32\\Sysprep\\sysprep.exe /generalize /oobe /unattend:A:\\Sysprep_Unattend.xml", + "shutdown_timeout": "1h", + + "export": { + "images": false + } + }, + { + "type": "vsphere-iso", + "name": "srv2019-physical", + + "vcenter_server": "{{user `vcenter_server`}}", + "username": "{{user `vsphere_username`}}", + "password": "{{user `vsphere_password`}}", + "insecure_connection": "true", + + "vm_name": "{{user `vm_guestos`}}-{{user `vm_name`}}-physical", + "datastore": "{{user `vsphere_datastore`}}", + "folder": "{{user `vsphere_folder`}}", + "datacenter": "{{user `vsphere_datacenter`}}", + "host": "{{user `vsphere_host`}}", + "boot_order": "disk,cdrom", + + "guest_os_type": "windows9Server64Guest", + + "communicator": "winrm", + "winrm_username": "administrator", + "winrm_password": "{{user `winrm_password`}}", + "winrm_timeout": "10m", + + "cpus": 2, + "RAM": 8192, + + "network_adapters": [ + { + "network": "{{user `vsphere_network`}}", + "network_card": "vmxnet3" + } + ], + "storage": [ + { + "disk_size": 20480, + "disk_thin_provisioned": true + } + ], + "disk_controller_type": "lsilogic-sas", + "usb_controller": "xhci", + + "iso_url": "https://{{user `repo_username`}}:{{user `repo_password`}}@sn.itch.fyi/Repository/iso/Microsoft/Windows%20Server%202019/LTSC/en_windows_server_2019_x64_dvd_4cb967d8.iso", + "iso_checksum": "sha256:4c5dd63efee50117986a2e38d4b3a3fbaf3c1c15e2e7ea1d23ef9d8af148dd2d", + "iso_paths": [ + "[Datastore01.NAS] contentlib-5c2187fa-55c5-4285-b06b-3f5f1ff9428d/e9342f62-6132-4044-bd42-48cab8c77034/VMware-tools-windows-11.2.1-17243207_4f88be10-b163-446b-ad7d-992e63b0e3ac.iso" + ], + + "floppy_files": [ + "packer/preseed/Server2019/Autounattend.xml", + "packer/preseed/Server2019/Sysprep_Unattend.xml", + "scripts/Set-NetworkProfile.ps1", + "scripts/Disable-WinRM.ps1", + "scripts/Enable-WinRM.ps1", + "scripts/Install-VMwareTools.cmd", + "scripts/Uninstall-VMwareTools.Sysprep.cmd" + ], + + "boot_command": "", + "boot_wait": "5m", + + "shutdown_command": "A:\\Uninstall-VMwareTools.Sysprep.cmd", + "shutdown_timeout": "1h" + } + ], + "provisioners": [ + { + "type": "windows-update" + }, + { + "type": "powershell", + "inline": [ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12", + "Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" + ] + }, + { + "type": "powershell", + "inline": [ + "choco config set --name=limit-output --value=LimitOutput", + "choco install -y 7zip.install", + "choco install -y sysinternals" + ], + "valid_exit_codes": [0, 3010] + }, + { + "type": "windows-update" + }, + { + "type": "windows-restart", + "restart_check_command":"powershell -command \"& {Write-Output 'Probing restart status'}\"" + } + ], + "post-processors": [[ + { + "only": ["srv2019-virtual"], + "type": "shell-local", + "inline": [ + "pwsh -file scripts/Apply-VMConfigSpec.ps1 \\", + " -VMConfigSpec 'Server2019' \\", + " -VMName {{user `vm_guestos`}}-{{user `vm_name`}} \\", + " -VSpherePassword '{{user `vsphere_password`}}'" + ] + }, + { + "only": ["srv2019-virtual"], + "type": "vsphere", + "host": "{{user `vcenter_server`}}", + "username": "{{user `vsphere_username`}}", + "password": "{{user `vsphere_password`}}", + "insecure": true, + "vm_name": "Windows-Server-2019-LTSC", + "datacenter": "{{user `vsphere_datacenter`}}", + "cluster": "{{user `vsphere_host`}}", + "vm_folder": "{{user `vsphere_templatefolder`}}", + "datastore": "{{user `vsphere_datastore`}}", + "disk_mode": "thin", + "vm_network": "{{user `vsphere_network`}}", + "overwrite": true, + "keep_input_artifact": true + }, + { + "only": ["srv2019-virtual"], + "type": "vsphere-template", + "host": "{{user `vcenter_server`}}", + "username": "{{user `vsphere_username`}}", + "password": "{{user `vsphere_password`}}", + "insecure": true, + "datacenter": "{{user `vsphere_datacenter`}}", + "folder": "{{user `vsphere_templatefolder`}}", + "reregister_vm": false + } + ]] + } diff --git a/scripts/Copy-DatastoreItem.ps1 b/scripts/Copy-DatastoreItem.ps1 new file mode 100644 index 0000000..aa24a17 --- /dev/null +++ b/scripts/Copy-DatastoreItem.ps1 @@ -0,0 +1,52 @@ +[CmdletBinding()] +Param( + [Parameter(Mandatory)] + [string]$VMName, + [Parameter(Mandatory)] + [string]$VSphereFQDN, + [Parameter(Mandatory)] + [string]$VSphereUsername, + [Parameter(Mandatory)] + [string]$VSpherePassword +) + +$PowerCliConfigurationSplat = @{ + Scope = 'User' + ParticipateInCEIP = $False + Confirm = $False + InvalidCertificateAction = 'Ignore' +} +Set-PowerCLIConfiguration @PowerCliConfigurationSplat | Out-Null + +$ConnectVIServerSplat = @{ + Server = $VSphereFQDN + User = "$VSphereUsername" + Password = "$VSpherePassword" + WarningAction = 'SilentlyContinue' +} +Connect-VIServer @ConnectVIServerSplat | Out-Null + +$GetVMSplat = @{ + Name = $VMName +} +$VM = Get-VM @GetVMSplat + +$GetHarddiskSplat = @{ + VM = $VM +} +$Harddisk = Get-Harddisk @GetHarddiskSplat +$VMFolder = ($Harddisk.Filename.Substring(0, $Harddisk.Filename.LastIndexOf('/')) -split ' ')[1] + +$NewDatastoreDriveSplat = @{ + Name = 'ds' + Datastore = ($VM | Get-Datastore) +} +New-DatastoreDrive @NewDatastoreDriveSplat + +$CopyDatastoreItemSplat = @{ + Item = "ds:\$($VMFolder)\*.vmdk" + Destination = (Get-Item $PWD) +} +Copy-DatastoreItem @CopyDatastoreItemSplat + +Disconnect-VIServer * -Confirm:$False \ No newline at end of file diff --git a/scripts/Disable-WinRM.ps1 b/scripts/Disable-WinRM.ps1 new file mode 100644 index 0000000..1ce9273 --- /dev/null +++ b/scripts/Disable-WinRM.ps1 @@ -0,0 +1,8 @@ +netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block +netsh advfirewall firewall set rule group="Windows Remote Management" new enable=yes +$winrmService = Get-Service -Name WinRM +if ($winrmService.Status -eq "Running"){ + Disable-PSRemoting -Force +} +Stop-Service winrm +Set-Service -Name winrm -StartupType Disabled diff --git a/scripts/Enable-WinRM.ps1 b/scripts/Enable-WinRM.ps1 new file mode 100644 index 0000000..3d70efe --- /dev/null +++ b/scripts/Enable-WinRM.ps1 @@ -0,0 +1,18 @@ +$NetworkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}")) +$Connections = $NetworkListManager.GetNetworkConnections() +$Connections | ForEach-Object { $_.GetNetwork().SetCategory(1) } + +Enable-PSRemoting -Force +winrm quickconfig -q +winrm quickconfig -transport:http +winrm set winrm/config '@{MaxTimeoutms="1800000"}' +winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="800"}' +winrm set winrm/config/service '@{AllowUnencrypted="true"}' +winrm set winrm/config/service/auth '@{Basic="true"}' +winrm set winrm/config/client/auth '@{Basic="true"}' +winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port="5985"}' +netsh advfirewall firewall set rule group="Windows Remote Administration" new enable=yes +netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=allow +netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" profile=public new remoteip=any +Set-Service winrm -startuptype "auto" +Restart-Service winrm diff --git a/scripts/Install-VMwareTools.cmd b/scripts/Install-VMwareTools.cmd new file mode 100644 index 0000000..58f2b36 --- /dev/null +++ b/scripts/Install-VMwareTools.cmd @@ -0,0 +1,2 @@ +@rem Silent mode, basic UI, no reboot +e:\setup64 /s /v "/qb REBOOT=R" \ No newline at end of file diff --git a/scripts/MVMC/BlockList.xml b/scripts/MVMC/BlockList.xml new file mode 100644 index 0000000..d590aeb --- /dev/null +++ b/scripts/MVMC/BlockList.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8" ?> +<BlockList> + <!-- services to disable --> + <Services> + <Name>MVMCP2VAgent</Name> + <Name>VMTools</Name> + <Name> VMUpgradeHelper </Name> + <Name> vmvss </Name> + <Name>vmdesched</Name> + <Name>Virtual Server</Name> + <!-- Virtual Machine Helper --> + <Name>vmh</Name> + <!-- Xen-specific service --> + <Name>xensvc</Name> + </Services> + <!-- drivers to disable --> + <Drivers> + <Name>vmx_svga</Name> + <Name>vmmouse</Name> + <Name>vmscsi</Name> + <Name>amdpcn</Name> + <Name>PCnet</Name> + <Name>VMMEMCTL</Name> + + <Name> pvscsi </Name> + <Name> vmci </Name> + <Name> vmmouse </Name> + <Name> vmaudio </Name> + <Name> vmrawdsk </Name> + <Name> vmxnet </Name> + <Name> vmxnet3ndis6 </Name> + <Name> vm3dmp </Name> + <Name> vmdebug </Name> + <Name> vmxnet3ndis5 </Name> + + + <Name>cirrus</Name> + <!-- storage drivers --> + <Name>buslogic</Name> + <Name>symc810</Name> + <Name>cpqarray</Name> + <Name>pcntn4m</Name> + <Name>cpqnf3</Name> + <Name>MRaidNT</Name> + <Name>Symc8XX</Name> + <!-- VIA chipset drivers --> + <Name>viaide</Name> + <Name>VIAudio</Name> + <Name>VIAPFD</Name> + <Name>viafilter</Name> + <Name>viaagp</Name> + <Name>viaagp1</Name> + <!-- network drivers: Intel(R) PRO/100 --> + <Name>E100B</Name> + <!-- tape drivers --> + <Name>4mmdat</Name> + <Name>4mmdat-SeSFT</Name> + <Name>SCSIChanger</Name> + + <!-- Virtual Machine Monitor --> + <Name>vmm</Name> + <!-- Xen-specific drivers --> + <Name>xenevtchn</Name> + <Name>xenvbd</Name> + <Name>xennet</Name> + </Drivers> + <Programs> + <Name>ProMON</Name> + <Name>s3tray2</Name> + <Name>VMwareTray</Name> + <Name>VMwareUser</Name> + </Programs> +</BlockList> \ No newline at end of file diff --git a/scripts/MVMC/Microsoft.Accelerators.Framework.Core.dll b/scripts/MVMC/Microsoft.Accelerators.Framework.Core.dll new file mode 100644 index 0000000..15ffdcb Binary files /dev/null and b/scripts/MVMC/Microsoft.Accelerators.Framework.Core.dll differ diff --git a/scripts/MVMC/Microsoft.Accelerators.Framework.dll b/scripts/MVMC/Microsoft.Accelerators.Framework.dll new file mode 100644 index 0000000..714ec9b Binary files /dev/null and b/scripts/MVMC/Microsoft.Accelerators.Framework.dll differ diff --git a/scripts/MVMC/Microsoft.Accelerators.Mvmc.Engine.dll b/scripts/MVMC/Microsoft.Accelerators.Mvmc.Engine.dll new file mode 100644 index 0000000..ae32db5 Binary files /dev/null and b/scripts/MVMC/Microsoft.Accelerators.Mvmc.Engine.dll differ diff --git a/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshCommon.dll b/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshCommon.dll new file mode 100644 index 0000000..4dab6e8 Binary files /dev/null and b/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshCommon.dll differ diff --git a/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshWrapper_x64.dll b/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshWrapper_x64.dll new file mode 100644 index 0000000..eab48e2 Binary files /dev/null and b/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshWrapper_x64.dll differ diff --git a/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshWrapper_x86.dll b/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshWrapper_x86.dll new file mode 100644 index 0000000..9adbdf0 Binary files /dev/null and b/scripts/MVMC/Microsoft.Accelerators.Mvmc.ScxSshWrapper_x86.dll differ diff --git a/scripts/MVMC/Microsoft.Practices.ServiceLocation.dll b/scripts/MVMC/Microsoft.Practices.ServiceLocation.dll new file mode 100644 index 0000000..330e60e Binary files /dev/null and b/scripts/MVMC/Microsoft.Practices.ServiceLocation.dll differ diff --git a/scripts/MVMC/Microsoft.Practices.Unity.dll b/scripts/MVMC/Microsoft.Practices.Unity.dll new file mode 100644 index 0000000..b3ca3ce Binary files /dev/null and b/scripts/MVMC/Microsoft.Practices.Unity.dll differ diff --git a/scripts/MVMC/Microsoft.Samples.WindowsAzure.ServiceManagement.dll b/scripts/MVMC/Microsoft.Samples.WindowsAzure.ServiceManagement.dll new file mode 100644 index 0000000..a07b399 Binary files /dev/null and b/scripts/MVMC/Microsoft.Samples.WindowsAzure.ServiceManagement.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.CloudService.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.CloudService.dll new file mode 100644 index 0000000..dcc2e64 Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.CloudService.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.ConsoleAppUtils.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.ConsoleAppUtils.dll new file mode 100644 index 0000000..d7762a3 Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.ConsoleAppUtils.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.Service.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.Service.dll new file mode 100644 index 0000000..d3e036d Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.Service.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.ServiceBus.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.ServiceBus.dll new file mode 100644 index 0000000..3353bc9 Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.ServiceBus.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.ServiceManagement.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.ServiceManagement.dll new file mode 100644 index 0000000..7aae384 Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.ServiceManagement.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.SqlDatabase.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.SqlDatabase.dll new file mode 100644 index 0000000..69839bf Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.SqlDatabase.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.Sync.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.Sync.dll new file mode 100644 index 0000000..3e5cd36 Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.Sync.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.Tools.Vhd.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.Tools.Vhd.dll new file mode 100644 index 0000000..4e138ae Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.Tools.Vhd.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.Websites.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.Websites.dll new file mode 100644 index 0000000..bf1863d Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.Websites.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Management.dll b/scripts/MVMC/Microsoft.WindowsAzure.Management.dll new file mode 100644 index 0000000..febdfcf Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Management.dll differ diff --git a/scripts/MVMC/Microsoft.WindowsAzure.Storage.dll b/scripts/MVMC/Microsoft.WindowsAzure.Storage.dll new file mode 100644 index 0000000..0d29d8d Binary files /dev/null and b/scripts/MVMC/Microsoft.WindowsAzure.Storage.dll differ diff --git a/scripts/MVMC/MvmcCmdlet.dll b/scripts/MVMC/MvmcCmdlet.dll new file mode 100644 index 0000000..5cef267 Binary files /dev/null and b/scripts/MVMC/MvmcCmdlet.dll differ diff --git a/scripts/MVMC/MvmcCmdlet.psd1 b/scripts/MVMC/MvmcCmdlet.psd1 new file mode 100644 index 0000000..a2be3f7 Binary files /dev/null and b/scripts/MVMC/MvmcCmdlet.psd1 differ diff --git a/scripts/MVMC/Sshlib_x64.dll b/scripts/MVMC/Sshlib_x64.dll new file mode 100644 index 0000000..ce68651 Binary files /dev/null and b/scripts/MVMC/Sshlib_x64.dll differ diff --git a/scripts/MVMC/Sshlib_x86.dll b/scripts/MVMC/Sshlib_x86.dll new file mode 100644 index 0000000..4658589 Binary files /dev/null and b/scripts/MVMC/Sshlib_x86.dll differ diff --git a/scripts/MVMC/System.Reactive.Core.dll b/scripts/MVMC/System.Reactive.Core.dll new file mode 100644 index 0000000..b893f83 Binary files /dev/null and b/scripts/MVMC/System.Reactive.Core.dll differ diff --git a/scripts/MVMC/System.Reactive.Interfaces.dll b/scripts/MVMC/System.Reactive.Interfaces.dll new file mode 100644 index 0000000..3dbb203 Binary files /dev/null and b/scripts/MVMC/System.Reactive.Interfaces.dll differ diff --git a/scripts/MVMC/System.Reactive.Linq.dll b/scripts/MVMC/System.Reactive.Linq.dll new file mode 100644 index 0000000..35d022a Binary files /dev/null and b/scripts/MVMC/System.Reactive.Linq.dll differ diff --git a/scripts/MVMC/System.Reactive.PlatformServices.dll b/scripts/MVMC/System.Reactive.PlatformServices.dll new file mode 100644 index 0000000..77f2db4 Binary files /dev/null and b/scripts/MVMC/System.Reactive.PlatformServices.dll differ diff --git a/scripts/MVMC/System.Reactive.Providers.dll b/scripts/MVMC/System.Reactive.Providers.dll new file mode 100644 index 0000000..fabc533 Binary files /dev/null and b/scripts/MVMC/System.Reactive.Providers.dll differ diff --git a/scripts/MVMC/System.Reactive.Windows.Threading.dll b/scripts/MVMC/System.Reactive.Windows.Threading.dll new file mode 100644 index 0000000..1c7840f Binary files /dev/null and b/scripts/MVMC/System.Reactive.Windows.Threading.dll differ diff --git a/scripts/New-WindowsImageJob.ps1 b/scripts/New-WindowsImageJob.ps1 new file mode 100644 index 0000000..634d41e --- /dev/null +++ b/scripts/New-WindowsImageJob.ps1 @@ -0,0 +1,51 @@ +#Requires -Modules 'dism' +Param( + [Parameter(Mandatory)] + [string]$ImageName, + [Parameter(Mandatory)] + [string]$SourceFolder, + [Parameter(Mandatory)] + [string]$DestinationFile +) + +$StartJobSplat = @{ + ArgumentList = $ImageName, $SourceFolder, $DestinationFile + ScriptBlock = { + Param( + $ImageName, + $SourceFolder, + $DestinationFile + ) + + $NewWindowsImageSplat = @{ + Name = $ImageName + CapturePath = $SourceFolder + ImagePath = $DestinationFile + Verify = $True + } + New-WindowsImage @NewWindowsImageSplat + } +} +$Job = Start-Job @StartJobSplat + +While ($Job.State -eq 'Running') { + $GetItemSplat = @{ + Path = $DestinationFile + ErrorAction = 'SilentlyContinue' + } + $OutputFile = Get-Item @GetItemSplat + If ($OutputFile) { + Write-Host "Export in progress ... $($OutputFile.FullName); Size: $('{0:n2}' -f ($OutputFile.Length / 1MB))MB" + } + Else { + Write-Host "Export initiating ... " + } + + $StartSleepSplat = @{ + Seconds = 30 + } + Start-Sleep @StartSleepSplat +} + +Receive-Job $Job +Remove-Job $Job \ No newline at end of file diff --git a/scripts/Remove-Resources.ps1 b/scripts/Remove-Resources.ps1 new file mode 100644 index 0000000..31c964d --- /dev/null +++ b/scripts/Remove-Resources.ps1 @@ -0,0 +1,39 @@ +[CmdletBinding()] +Param( + [Parameter(Mandatory)] + [string]$VMName, + [Parameter(Mandatory)] + [string]$VSphereFQDN, + [Parameter(Mandatory)] + [string]$VSphereUsername, + [Parameter(Mandatory)] + [string]$VSpherePassword +) + +$PowerCliConfigurationSplat = @{ + Scope = 'User' + ParticipateInCEIP = $False + Confirm = $False + InvalidCertificateAction = 'Ignore' +} +Set-PowerCLIConfiguration @PowerCliConfigurationSplat | Out-Null + +$ConnectVIServerSplat = @{ + Server = $VSphereFQDN + User = "$VSphereUsername" + Password = "$VSpherePassword" + WarningAction = 'SilentlyContinue' +} +Connect-VIServer @ConnectVIServerSplat | Out-Null + +$RemoveVMSplat = @{ + VM = "$($VMName)*" + DeletePermanently = $True + Confirm = $False + ErrorAction = 'SilentlyContinue' +} +Remove-VM @RemoveVMSplat + +# Also delete ISO/floppy? + +Disconnect-VIServer * -Confirm:$False \ No newline at end of file diff --git a/scripts/Set-NetworkProfile.ps1 b/scripts/Set-NetworkProfile.ps1 new file mode 100644 index 0000000..7433079 --- /dev/null +++ b/scripts/Set-NetworkProfile.ps1 @@ -0,0 +1,23 @@ +# You cannot enable Windows PowerShell Remoting on network connections that are set to Public +# Spin through all the network locations and if they are set to Public, set them to Private +# using the INetwork interface: +# http://msdn.microsoft.com/en-us/library/windows/desktop/aa370750(v=vs.85).aspx +# For more info, see: +# http://blogs.msdn.com/b/powershell/archive/2009/04/03/setting-network-location-to-private.aspx + +# Network location feature was only introduced in Windows Vista - no need to bother with this +# if the operating system is older than Vista +if([environment]::OSVersion.version.Major -lt 6) { return } + +# You cannot change the network location if you are joined to a domain, so abort +if(1,3,4,5 -contains (Get-WmiObject win32_computersystem).DomainRole) { return } + +# Get network connections +$networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}")) +$connections = $networkListManager.GetNetworkConnections() + +$connections |foreach { + Write-Host $_.GetNetwork().GetName()"category was previously set to"$_.GetNetwork().GetCategory() + $_.GetNetwork().SetCategory(1) + Write-Host $_.GetNetwork().GetName()"changed to category"$_.GetNetwork().GetCategory() +} diff --git a/scripts/Uninstall-VMwareTools.Sysprep.cmd b/scripts/Uninstall-VMwareTools.Sysprep.cmd new file mode 100644 index 0000000..f75b7a5 --- /dev/null +++ b/scripts/Uninstall-VMwareTools.Sysprep.cmd @@ -0,0 +1,7 @@ +@rem Uninstall VMware Tools +@rem (wait for orphaned child process to finish) +@rem Silent mode, basic UI, no reboot +start "Uninstall VMware Tools" /b /w e:\setup64 /s /v "/qb REBOOT=R REMOVE=ALL" + +@rem Initiate Sysprep +C:\Windows\System32\Sysprep\sysprep.exe /generalize /oobe /unattend:A:\Sysprep_Unattend.xml /quiet /shutdown \ No newline at end of file diff --git a/scripts/Update-Manifest.ps1 b/scripts/Update-Manifest.ps1 new file mode 100644 index 0000000..03e3ff8 --- /dev/null +++ b/scripts/Update-Manifest.ps1 @@ -0,0 +1,55 @@ +#Requires -Modules 'powershell-yaml' +[CmdletBinding()] +Param( + [Parameter(Mandatory)] + [ValidateScript({ + If (Test-Path($_)) { + $True + } Else { + Throw "'$_' is not a valid filename (within working directory '$PWD'), or access denied; aborting." + } + })] + [string]$ManifestFileName +) + +$GetItemSplat = @{ + Path = $ManifestFileName +} +$ManifestFile = Get-Item @GetItemSplat + +$SetLocationSplat = @{ + Path = $ManifestFile.DirectoryName +} +Set-Location @SetLocationSplat + +$GetContentSplat = @{ + Path = $ManifestFile.FullName +} +$Manifest = Get-Content @GetContentSplat + +$UpdatedManifest = ForEach ($Line in $Manifest) { + Write-Host "Processing '$($Line)' ..." + If ($Line -match '^SHA256\((.+)\)= ([0-9a-fA-F]{64})$') { + If (Test-Path $Matches[1]) { + $GetFileHashSplat = @{ + Path = $Matches[1] + Algorithm = 'SHA256' + } + Write-Host "Updating checksum..." + "SHA256($($Matches[1]))= $((Get-FileHash @GetFileHashSplat).Hash)" + } + } +} + +If ($UpdatedManifest -ne $Null) { + $SetContentSplat = @{ + Path = $ManifestFile.FullName + Value = $UpdatedManifest + Force = $True + Confirm = $False + } + Set-Content @SetContentSplat +} Else { + Write-Host "Failed updating manifest." + Exit 1 +} diff --git a/scripts/Update-OvfConfiguration.ps1 b/scripts/Update-OvfConfiguration.ps1 new file mode 100644 index 0000000..07908fa --- /dev/null +++ b/scripts/Update-OvfConfiguration.ps1 @@ -0,0 +1,253 @@ +#Requires -Modules 'powershell-yaml' +[CmdletBinding()] +Param( + [Parameter(Mandatory)] + [ValidateScript({ + If (Test-Path($_)) { + $True + } Else { + Throw "'$_' is not a valid filename (within working directory '$PWD'), or access denied; aborting." + } + })] + [string]$OVFFile, + [hashtable]$Parameter +) + +$GetContentSplat = @{ + Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', ".yml") + Raw = $True +} +$RawContent = Get-Content @GetContentSplat +$ConvertFromYamlSplat = @{ + Yaml = $RawContent + AllDocuments = $True +} +$YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat + +# Check if the respective .yml file declared substitutions which need to be parsed +If (($YamlDocuments.Count -gt 1) -and $YamlDocuments[-1].Variables) { + ForEach ($Pattern in $YamlDocuments[-1].Variables) { + $RawContent = $RawContent -replace "\{\{ ($($Pattern.Name)) \}\}", [string](Invoke-Expression -Command $Pattern.Expression) + } + # Perform conversion to Yaml again, now with parsed file contents + $ConvertFromYamlSplat = @{ + Yaml = $RawContent + AllDocuments = $True + } + $YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat + $OVFConfig = $YamlDocuments[0..($YamlDocuments.Count - 2)] +} +Else { + $OVFConfig = $YamlDocuments +} + +$SourceFile = Get-Item -Path $OVFFile +$GetContentSplat = @{ + Path = $SourceFile.FullName +} +$XML = [xml](Get-Content @GetContentSplat) +$NS = [System.Xml.XmlNamespaceManager]$XML.NameTable +[void]$NS.AddNamespace('Any', $XML.DocumentElement.xmlns) + +If ($OVFConfig.DeploymentConfigurations.Count -gt 0) { + $XMLSection = $XML.CreateElement('DeploymentOptionSection', $XML.DocumentElement.xmlns) + $XMLSectionInfo = $XML.CreateElement('Info', $XML.DocumentElement.xmlns) + $XMLSectionInfo.InnerText = 'Deployment Type' + [void]$XMLSection.AppendChild($XMLSectionInfo) + + ForEach ($Configuration in $OVFConfig.DeploymentConfigurations) { + $XMLConfig = $XML.CreateElement('Configuration', $XML.DocumentElement.xmlns) + + $XMLConfigAttrId = $XML.CreateAttribute('id', $XML.DocumentElement.ovf) + $XMLConfigAttrId.Value = $Configuration.Id + + $XMLConfigLabel = $XML.CreateElement('Label', $XML.DocumentElement.xmlns) + $XMLConfigLabel.InnerText = $Configuration.Label + + $XMLConfigDescription = $XML.CreateElement('Description', $XML.DocumentElement.xmlns) + $XMLConfigDescription.InnerText = $Configuration.Description + + [void]$XMLConfig.Attributes.Append($XMLConfigAttrId) + [void]$XMLConfig.AppendChild($XMLConfigLabel) + [void]$XMLConfig.AppendChild($XMLConfigDescription) + + [void]$XMLSection.AppendChild($XMLConfig) + } + [void]$XML.SelectSingleNode('//Any:Envelope', $NS).InsertAfter($XMLSection, $XML.SelectSingleNode('//Any:NetworkSection', $NS)) + Write-Host "Inserted 'DeploymentOptionSection' with $($Configuration.Count) nodes" +} + +$XMLAttrTransport = $XML.CreateAttribute('transport', $XML.DocumentElement.ovf) +$XMLAttrTransport.Value = 'com.vmware.guestInfo' +[void]$XML.SelectSingleNode('//Any:VirtualHardwareSection', $NS).Attributes.Append($XMLAttrTransport) +ForEach ($ExtraConfig in $OVFConfig.AdvancedOptions) { + $XMLExtraConfig = $XML.CreateElement('vmw:ExtraConfig', $XML.DocumentElement.vmw) + + $XMLExtraConfigAttrRequired = $XML.CreateAttribute('required', $XML.DocumentElement.ovf) + $XMLExtraConfigAttrRequired.Value = "$([boolean]$ExtraConfig.Required)".ToLower() + $XMLExtraConfigAttrKey = $XML.CreateAttribute('key', $XML.DocumentElement.vmw) + $XMLExtraConfigAttrKey.Value = $ExtraConfig.Key + $XMLExtraConfigAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.vmw) + $XMLExtraConfigAttrValue.Value = $ExtraConfig.Value + + [void]$XMLExtraConfig.Attributes.Append($XMLExtraConfigAttrRequired) + [void]$XMLExtraConfig.Attributes.Append($XMLExtraConfigAttrKey) + [void]$XMLExtraConfig.Attributes.Append($XMLExtraConfigAttrValue) + [void]$XML.SelectSingleNode('//Any:VirtualHardwareSection', $NS).AppendChild($XMLExtraConfig) +} +Write-Host "Added $($OVFConfig.AdvancedOptions.Count) 'vmw:ExtraConfig' nodes" + +$XMLProductSection = $XML.SelectSingleNode('//Any:ProductSection', $NS) +If ($XMLProductSection -eq $Null) { + $XMLProductSection = $XML.CreateElement('ProductSection', $XML.DocumentElement.xmlns) + [void]$XML.SelectSingleNode('//Any:VirtualSystem', $NS).AppendChild($XMLProductSection) + Write-Host "Inserted 'ProductSection'" +} Else { + ForEach ($Child in $XMLProductSection.SelectNodes('//Any:ProductSection/child::*', $NS)) { + [void]$Child.ParentNode.RemoveChild($Child) + } + Write-Host "Destroyed pre-existing children in 'ProductSection'" +} +$XMLProductSectionInfo = $XML.CreateElement('Info', $XML.DocumentElement.xmlns) +$XMLProductSectionInfo.InnerText = 'Information about the installed software' +[void]$XMLProductSection.AppendChild($XMLProductSectionInfo) +Write-Host "Inserted new 'Info' into 'ProductSection'" + +ForEach ($Category in $OVFConfig.PropertyCategories) { + If ($Category.Name -ne '') { + $XMLCategory = $XML.CreateElement('Category', $XML.DocumentElement.xmlns) + $XMLCategory.InnerText = $Category.Name + [void]$XMLProductSection.AppendChild($XMLCategory) + Write-Host "Inserted new 'Category' into 'ProductSection'" + } + + ForEach ($Property in $Category.ProductProperties) { + $XMLProperty = $XML.CreateElement('Property', $XML.DocumentElement.xmlns) + + $XMLPropertyAttrKey = $XML.CreateAttribute('key', $XML.DocumentElement.ovf) + $XMLPropertyAttrKey.Value = $Property.Key + $XMLPropertyAttrType = $XML.CreateAttribute('type', $XML.DocumentElement.ovf) + Switch -regex ($Property.Type) { + 'boolean' { + $XMLPropertyAttrType.Value = 'boolean' + } + 'int' { + $XMLPropertyAttrType.Value = 'uint8' + $Qualifiers = @() + If ($Property.Type -match 'int\((\d*)\.\.(\d*)\)') { + If ($Matches[1]) { + $Qualifiers += "MinValue($($Matches[1]))" + } + If ($Matches[2]) { + $Qualifiers += "MaxValue($($Matches[2]))" + } + $XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf) + $XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' ' + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers) + } + } + 'ip' { + $XMLPropertyAttrType.Value = 'string' + $XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.vmw) + $XMLPropertyAttrQualifiers.Value = 'Ip' + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers) + } + 'password' { + $XMLPropertyAttrType.Value = 'string' + $XMLPropertyAttrPassword = $XML.CreateAttribute('password', $XML.DocumentElement.ovf) + $XMLPropertyAttrPassword.Value = 'true' + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrPassword) + + $Qualifiers = @() + If ($Property.Type -match 'password\((\d*)\.\.(\d*)\)') { + If ($Matches[1]) { + $Qualifiers += "MinLen($($Matches[1]))" + } + If ($Matches[2]) { + $Qualifiers += "MaxLen($($Matches[2]))" + } + $XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf) + $XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' ' + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers) + } + } + 'string' { + $XMLPropertyAttrType.Value = 'string' + $Qualifiers = @() + If ($Property.Type -match 'string\((\d*)\.\.(\d*)\)') { + If ($Matches[1]) { + $Qualifiers += "MinLen($($Matches[1]))" + } + If ($Matches[2]) { + $Qualifiers += "MaxLen($($Matches[2]))" + } + $XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf) + $XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' ' + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers) + } ElseIf ($Property.Type -match 'string\[(.*)\]') { + $XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf) + $XMLPropertyAttrQualifiers.Value = "ValueMap{$($Matches[1] -replace '","', '", "')}" + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers) + } + } + } + $XMLPropertyAttrUserConfigurable = $XML.CreateAttribute('userConfigurable', $XML.DocumentElement.ovf) + $XMLPropertyAttrUserConfigurable.Value = "$([boolean]$Property.UserConfigurable)".ToLower() + $XMLPropertyAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf) + If ($Property.Type -eq 'boolean') { + $XMLPropertyAttrValue.Value = "$([boolean]$Property.DefaultValue)".ToLower() + } Else { + $XMLPropertyAttrValue.Value = $Property.DefaultValue + } + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrKey) + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrType) + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrUserConfigurable) + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrValue) + + If ($Property.Label) { + $XMLPropertyLabel = $XML.CreateElement('Label', $XML.DocumentElement.xmlns) + $XMLPropertyLabel.InnerText = $Property.Label + [void]$XMLProperty.AppendChild($XMLPropertyLabel) + } + If ($Property.Description) { + $XMLPropertyDescription = $XML.CreateElement('Description', $XML.DocumentElement.xmlns) + $XMLPropertyDescription.InnerText = $Property.Description + [void]$XMLProperty.AppendChild($XMLPropertyDescription) + } + + If (($Property.Configurations.Count -eq 1) -and ($Property.Configurations -eq '*')) { + $XMLPropertyAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf) + $XMLPropertyAttrConfiguration.Value = $OVFConfig.DeploymentConfigurations.Id -join ' ' + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrConfiguration) + } ElseIf ($Property.Configurations.Count -gt 0) { + $XMLPropertyAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf) + $XMLPropertyAttrConfiguration.Value = $Property.Configurations -join ' ' + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrConfiguration) + } + + If ($Property.Value.Count -eq 1) { + $XMLPropertyAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf) + $XMLPropertyAttrValue.Value = $Property.Value + [void]$XMLProperty.Attributes.Append($XMLPropertyAttrValue) + } ElseIf ($Property.Value.Count -gt 1) { + ForEach ($Value in $Property.Value) { + $XMLValue = $XML.CreateElement('Value', $XML.DocumentElement.xmlns) + + $XMLValueAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf) + $XMLValueAttrValue.Value = $Value + $XMLValueAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf) + $XMLValueAttrConfiguration.Value = $Value + + [void]$XMLValue.Attributes.Append($XMLValueAttrValue) + [void]$XMLValue.Attributes.Append($XMLValueAttrConfiguration) + + [void]$XMLProperty.AppendChild($XMLValue) + } + } + + [void]$XMLProductSection.AppendChild($XMLProperty) + } + Write-Host "Inserted $($Category.ProductProperties.Count) new node(s) into 'ProductSection'" +} + +$XML.Save($SourceFile.FullName) diff --git a/scripts/Update-OvfConfiguration.yml b/scripts/Update-OvfConfiguration.yml new file mode 100644 index 0000000..44372c3 --- /dev/null +++ b/scripts/Update-OvfConfiguration.yml @@ -0,0 +1,53 @@ +DeploymentConfigurations: [] +PropertyCategories: +- Name: 1) Operating System + ProductProperties: + - Key: guestinfo.hostname + Type: string(1..15) + Label: Hostname* + Description: '(max length: 15 characters)' + DefaultValue: '' + UserConfigurable: true +- Name: 2) Networking + ProductProperties: + - Key: guestinfo.ipaddress + Type: ip + Label: IP Address* + Description: '' + DefaultValue: '' + UserConfigurable: true + - Key: guestinfo.prefixlength + Type: int(8..32) + Label: Subnet prefix length* + Description: '' + DefaultValue: '24' + UserConfigurable: true + - Key: guestinfo.dnsserver + Type: ip + Label: DNS server* + Description: '' + DefaultValue: '' + UserConfigurable: true + - Key: guestinfo.gateway + Type: ip + Label: Gateway* + Description: '' + DefaultValue: '' + UserConfigurable: true +AdvancedOptions: +- Key: appliance.name + Value: "{{ appliance.name }}" + Required: false +- Key: appliance.version + Value: "{{ appliance.version }}" + Required: false + +--- +Variables: +- Name: appliance.name + Expression: | + $Parameter['appliance.name'] +- Name: appliance.version + Expression: | + $Parameter['appliance.version'] + \ No newline at end of file