├── example ├── windows │ ├── build.nutanix.pkr.hcl │ ├── files │ │ ├── scripts │ │ │ ├── SetupComplete.cmd │ │ │ ├── StaticIP.ps1 │ │ │ ├── EnableWinRMforPacker.ps1 │ │ │ └── ConfigureRemotingForAnsible.ps1 │ │ └── autounattend.xml │ ├── settings.auto.pkrvars.hcl │ ├── variables.pkr.hcl │ ├── README.md │ └── source.nutanix.pkr.hcl ├── init │ └── plugin.pkr.hcl ├── scripts │ ├── cloud-init │ │ ├── cloud-config-centos.yaml │ │ ├── cloud-config-ubuntu.yaml │ │ └── autoinstall-ubuntu.yaml │ ├── cleanup.ps1 │ ├── ks.cfg │ ├── win-update.ps1 │ └── gui │ │ └── autounattend.xml ├── README.md ├── settings.auto.pkrvars.hcl ├── variables.pkr.hcl ├── build.nutanix.pkr.hcl └── source.nutanix.pkr.hcl ├── test └── e2e │ ├── centos-img │ ├── build.pkr.hcl │ ├── variables.pkr.hcl │ └── source.pkr.hcl │ └── centos-iso │ ├── build.pkr.hcl │ ├── variables.pkr.hcl │ ├── scripts │ └── ks.cfg │ └── source.pkr.hcl ├── .web-docs ├── metadata.hcl ├── README.md ├── scripts │ └── compile-to-webdocs.sh └── components │ └── builder │ └── nutanix │ └── README.md ├── main.go ├── .github ├── release.yaml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── workflows │ ├── ensure-docs-compiled.yaml │ ├── trivy-scan.yaml │ ├── synopsys-schedule.yaml │ ├── test-plugin-example.yml │ ├── codeql-analysis.yml │ ├── integration.yml │ ├── release.yml │ ├── notify-integration-release-via-manual.yaml │ ├── notify-integration-release-via-tag.yaml │ ├── test-plugin-e2e.yaml │ └── synopsys.yaml ├── dependabot.yml └── PULL_REQUEST_TEMPLATE.md ├── version └── version.go ├── .gitignore ├── Makefile ├── docs-partials └── builder │ └── nutanix │ └── WaitIpConfig-not-required.mdx ├── CONTRIBUTING.md ├── docs ├── README.md └── builders │ └── nutanix.mdx ├── .goreleaser.yml ├── README.md ├── go.mod └── LICENSE /example/windows/build.nutanix.pkr.hcl: -------------------------------------------------------------------------------- 1 | build { 2 | sources = [ 3 | "source.nutanix.windows11" 4 | ] 5 | 6 | } 7 | -------------------------------------------------------------------------------- /example/init/plugin.pkr.hcl: -------------------------------------------------------------------------------- 1 | packer { 2 | required_plugins { 3 | nutanix = { 4 | version = ">= 1.1.4" 5 | source = "github.com/nutanix-cloud-native/nutanix" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/scripts/cloud-init/cloud-config-centos.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | users: 3 | - name: centos 4 | sudo: ['ALL=(ALL) NOPASSWD:ALL'] 5 | chpasswd: 6 | list: | 7 | centos:packer 8 | expire: False 9 | ssh_pwauth: True 10 | -------------------------------------------------------------------------------- /example/scripts/cloud-init/cloud-config-ubuntu.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | users: 3 | - name: builder 4 | sudo: ['ALL=(ALL) NOPASSWD:ALL'] 5 | chpasswd: 6 | list: | 7 | builder:packer 8 | expire: False 9 | ssh_pwauth: True 10 | -------------------------------------------------------------------------------- /example/windows/files/scripts/SetupComplete.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Set static IP address 3 | :: powershell -NoProfile -ExecutionPolicy Bypass -File "f:\StaticIP.ps1" 4 | :: Enable WinRM 5 | powershell -NoProfile -ExecutionPolicy Bypass -File "f:\EnableWinRMforPacker.ps1" -------------------------------------------------------------------------------- /test/e2e/centos-img/build.pkr.hcl: -------------------------------------------------------------------------------- 1 | build { 2 | source "nutanix.centos" { 3 | name = "centos" 4 | } 5 | 6 | provisioner "shell" { 7 | environment_vars = [ 8 | "FOO=hello world", 9 | ] 10 | inline = [ 11 | "echo \"FOO is $FOO\" > example.txt", 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/e2e/centos-iso/build.pkr.hcl: -------------------------------------------------------------------------------- 1 | build { 2 | source "nutanix.centos" { 3 | name = "centos" 4 | } 5 | 6 | provisioner "shell" { 7 | environment_vars = [ 8 | "FOO=hello world", 9 | ] 10 | inline = [ 11 | "echo \"FOO is $FOO\" > example.txt", 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/scripts/cloud-init/autoinstall-ubuntu.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | autoinstall: 3 | version: 1 4 | identity: 5 | hostname: ubuntu-server 6 | password: "$6$exDY1mhS4KUYCE/2$zmn9ToZwTKLhCw.b4/b.ZRTIZM30JZ4QrOQ2aOXJ8yk96xpcCof0kxKwuX1kqLG/ygbJ1f8wxED22bTL4F46P0" 7 | username: ubuntu 8 | ssh: 9 | install-server: true 10 | allow-pw: true 11 | -------------------------------------------------------------------------------- /.web-docs/metadata.hcl: -------------------------------------------------------------------------------- 1 | # For full specification on the configuration of this file visit: 2 | # https://github.com/hashicorp/integration-template#metadata-configuration 3 | integration { 4 | name = "Nutanix" 5 | description = "A multi-component plugin can be used with Packer to create custom images." 6 | identifier = "packer/nutanix-cloud-native/nutanix" 7 | component { 8 | type = "builder" 9 | name = "Nutanix plugin" 10 | slug = "nutanix" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example/windows/settings.auto.pkrvars.hcl: -------------------------------------------------------------------------------- 1 | nutanix_username = "admin" 2 | nutanix_password = "XXX" 3 | nutanix_insecure = false 4 | nutanix_endpoint = "XXX" 5 | nutanix_port = 9440 6 | nutanix_cluster = "XXX" 7 | nutanix_subnet = "XXX" 8 | nutanix_storage_container_uuid = "XXX" 9 | windows_11_iso_image_name = "windows_11_business_editions_24h2_april_2025.iso" 10 | virtio_iso_image_name = "Nutanix-VirtIO-1.2.4.iso" 11 | winrm_username = "Administrator" 12 | winrm_password = "Nutanix.123!!" -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/hashicorp/packer-plugin-sdk/plugin" 8 | "github.com/nutanix-cloud-native/packer-plugin-nutanix/builder/nutanix" 9 | "github.com/nutanix-cloud-native/packer-plugin-nutanix/version" 10 | ) 11 | 12 | func main() { 13 | pps := plugin.NewSet() 14 | pps.RegisterBuilder(plugin.DEFAULT_NAME, new(nutanix.Builder)) 15 | pps.SetVersion(version.PluginVersion) 16 | err := pps.Run() 17 | if err != nil { 18 | fmt.Fprintln(os.Stderr, err.Error()) 19 | os.Exit(1) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/release.yaml: -------------------------------------------------------------------------------- 1 | # .github/release.yml 2 | 3 | changelog: 4 | exclude: 5 | labels: 6 | - ignore-for-release 7 | categories: 8 | - title: Breaking Changes 🛠 9 | labels: 10 | - Semver-Major 11 | - breaking-change 12 | - title: Exciting New Features 🎉 13 | labels: 14 | - Semver-Minor 15 | - enhancement 16 | - title: Bug Fixes 🐛 17 | labels: 18 | - bug 19 | - title: Documentation 📖 20 | labels: 21 | - documentation 22 | - title: Other Changes 23 | labels: 24 | - "*" -------------------------------------------------------------------------------- /test/e2e/centos-img/variables.pkr.hcl: -------------------------------------------------------------------------------- 1 | variable "nutanix_username" { 2 | type = string 3 | } 4 | 5 | variable "nutanix_password" { 6 | type = string 7 | sensitive = true 8 | } 9 | 10 | variable "nutanix_endpoint" { 11 | type = string 12 | } 13 | 14 | variable "nutanix_port" { 15 | type = number 16 | } 17 | 18 | variable "nutanix_insecure" { 19 | type = bool 20 | default = true 21 | } 22 | 23 | variable "nutanix_subnet" { 24 | type = string 25 | } 26 | 27 | variable "nutanix_cluster" { 28 | type = string 29 | } 30 | 31 | variable "test" { 32 | type = string 33 | } -------------------------------------------------------------------------------- /test/e2e/centos-iso/variables.pkr.hcl: -------------------------------------------------------------------------------- 1 | variable "nutanix_username" { 2 | type = string 3 | } 4 | 5 | variable "nutanix_password" { 6 | type = string 7 | sensitive = true 8 | } 9 | 10 | variable "nutanix_endpoint" { 11 | type = string 12 | } 13 | 14 | variable "nutanix_port" { 15 | type = number 16 | } 17 | 18 | variable "nutanix_insecure" { 19 | type = bool 20 | default = true 21 | } 22 | 23 | variable "nutanix_subnet" { 24 | type = string 25 | } 26 | 27 | variable "nutanix_cluster" { 28 | type = string 29 | } 30 | 31 | variable "test" { 32 | type = string 33 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature enhancement request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | /kind feature 8 | 9 | **Describe the solution you'd like** 10 | [A clear and concise description of what you want to happen.] 11 | 12 | 13 | **Anything else you would like to add:** 14 | [Miscellaneous information that will assist in solving the issue.] 15 | 16 | 17 | **Environment:** 18 | 19 | - packer-plugin-nutanix version (use `packer plugins installed`): 20 | - Packer version (use `packer version`): 21 | - OS (e.g. from `/etc/os-release`): -------------------------------------------------------------------------------- /.github/workflows/ensure-docs-compiled.yaml: -------------------------------------------------------------------------------- 1 | name: Ensure Docs are Compiled 2 | on: 3 | push: 4 | jobs: 5 | ensure-docs-compiled: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout 🛎 9 | uses: actions/checkout@v6.0.1 10 | - uses: actions/setup-go@v6 11 | - shell: bash 12 | run: make generate 13 | - shell: bash 14 | run: | 15 | if [[ -z "$(git status -s)" ]]; then 16 | echo "OK" 17 | else 18 | echo "Docs have been updated, but the compiled docs have not been committed." 19 | echo "Run 'make generate', and commit the result to resolve this error." 20 | exit 1 21 | fi 22 | 23 | -------------------------------------------------------------------------------- /example/windows/files/scripts/StaticIP.ps1: -------------------------------------------------------------------------------- 1 | $IP = "10.2.3.4" 2 | $MaskBits = 24 3 | $Gateway = "10.2.3.1" 4 | $DNS = "1.1.1.1" 5 | $IPType = "IPv4" 6 | 7 | $Adapter = Get-NetAdapter | Where-Object { $_.Status -eq "Up" } 8 | 9 | if (($Adapter | Get-NetIPConfiguration).Ipv4Address.IpAddress) { 10 | $Adapter | Remove-NetIPAddress -AddressFamily $IPType -Confirm:$false 11 | } 12 | 13 | if (($Adapter | Get-NetIPConfiguration).Ipv4DefaultGateway){ 14 | $Adapter | Remove-NetRoute -AddressFamily $IPType -Confirm:$false 15 | } 16 | 17 | $Adapter | New-NetIPAddress -IPAddress $IP -PrefixLength $MaskBits -DefaultGateway $Gateway -AddressFamily $IPType 18 | 19 | $Adapter | Set-DnsClientServerAddress -ServerAddresses $DNS -AddressFamily $IPType -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "github.com/hashicorp/packer-plugin-sdk/version" 5 | ) 6 | 7 | var ( 8 | // Version is the main version number that is being run at the moment. 9 | Version = "1.1.4" 10 | 11 | // VersionPrerelease is A pre-release marker for the Version. If this is "" 12 | // (empty string) then it means that it is a final release. Otherwise, this 13 | // is a pre-release such as "dev" (in development), "beta", "rc1", etc. 14 | VersionPrerelease = "dev" 15 | 16 | // VersionMetadata 17 | VersionMetadata = "" 18 | 19 | // PluginVersion is used by the plugin set to allow Packer to recognize 20 | // what version this plugin is. 21 | PluginVersion = version.NewPluginVersion(Version, VersionPrerelease, VersionMetadata) 22 | ) 23 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | ## Examples 2 | Validate Manifests: 3 | `packer validate .` 4 | 5 | Creating CentOS from local Image and running Provisioner: 6 | `packer build -only nutanix.centos .` 7 | 8 | Creating Ubuntu from Upstream Image and running Provisioner: 9 | `packer build -only nutanix.ubuntu .` 10 | 11 | Creating CentOS from ISO with Kickstart-File: 12 | `packer build -only nutanix.centos-kickstart .` 13 | 14 | Creating Ubuntu from ISO with Autoinstall: 15 | `packer build -only nutanix.ubuntu-autoinstall .` 16 | 17 | Windows Image (ISO Boot, VirtIO Drivers, cd_files) 18 | `packer build -only nutanix.windows .` 19 | 20 | Advanced Windows 11 EUC example is available in the [`windows`](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/tree/main/example/windows) directory -------------------------------------------------------------------------------- /example/settings.auto.pkrvars.hcl: -------------------------------------------------------------------------------- 1 | nutanix_username = "" 2 | nutanix_password = "" 3 | nutanix_insecure = false 4 | nutanix_endpoint = "" 5 | nutanix_port = 9440 6 | nutanix_cluster = "" 7 | nutanix_subnet = "" 8 | centos_iso_image_name = "" 9 | centos_disk_image_name = "" 10 | ubuntu_iso_image_name = "" 11 | ubuntu_disk_image_name = "" 12 | windows_2016_iso_image_name = "" 13 | virtio_iso_image_name = "" 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Tell us about a problem you are experiencing 4 | 5 | --- 6 | 7 | /kind bug 8 | 9 | **What steps did you take and what happened:** 10 | 11 | _A clear and concise description of what the bug is and how has this been tested. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration_ 12 | _Paste a full trace by launching packer with `PACKER_LOG=1 packer []`_ 13 | 14 | **What did you expect to happen:** 15 | 16 | 17 | **Anything else you would like to add:** 18 | 19 | _Miscellaneous information that will assist in solving the issue._ 20 | 21 | 22 | **Environment:** 23 | 24 | - packer-plugin-nutanix version (use `packer plugins installed`): 25 | - Packer version (use `packer version`): 26 | - OS (e.g. from `/etc/os-release`): -------------------------------------------------------------------------------- /example/variables.pkr.hcl: -------------------------------------------------------------------------------- 1 | variable "nutanix_username" { 2 | type = string 3 | } 4 | 5 | variable "nutanix_password" { 6 | type = string 7 | sensitive = true 8 | } 9 | 10 | variable "nutanix_endpoint" { 11 | type = string 12 | } 13 | 14 | variable "nutanix_port" { 15 | type = number 16 | } 17 | 18 | variable "nutanix_insecure" { 19 | type = bool 20 | default = true 21 | } 22 | 23 | variable "nutanix_subnet" { 24 | type = string 25 | } 26 | 27 | variable "nutanix_cluster" { 28 | type = string 29 | } 30 | 31 | variable "centos_iso_image_name" { 32 | type = string 33 | } 34 | 35 | variable "centos_disk_image_name" { 36 | type = string 37 | } 38 | 39 | variable "ubuntu_disk_image_name" { 40 | type = string 41 | } 42 | 43 | variable "ubuntu_iso_image_name" { 44 | type = string 45 | } 46 | 47 | variable "windows_2016_iso_image_name" { 48 | type = string 49 | } 50 | 51 | variable "virtio_iso_image_name" { 52 | type = string 53 | } -------------------------------------------------------------------------------- /example/windows/variables.pkr.hcl: -------------------------------------------------------------------------------- 1 | variable "nutanix_username" { 2 | type = string 3 | } 4 | 5 | variable "nutanix_password" { 6 | type = string 7 | sensitive = true 8 | } 9 | 10 | variable "nutanix_endpoint" { 11 | type = string 12 | } 13 | 14 | variable "nutanix_port" { 15 | type = number 16 | } 17 | 18 | variable "nutanix_insecure" { 19 | type = bool 20 | default = true 21 | } 22 | 23 | variable "nutanix_subnet" { 24 | type = string 25 | } 26 | 27 | variable "nutanix_cluster" { 28 | type = string 29 | } 30 | 31 | variable "windows_11_iso_image_name" { 32 | type = string 33 | } 34 | 35 | variable "virtio_iso_image_name" { 36 | type = string 37 | } 38 | 39 | variable "winrm_username" { 40 | type = string 41 | } 42 | 43 | variable "winrm_password" { 44 | type = string 45 | } 46 | 47 | variable "nutanix_storage_container_uuid" { 48 | type = string 49 | description = "UUID of the storage container where the VM disk will be created." 50 | } -------------------------------------------------------------------------------- /example/build.nutanix.pkr.hcl: -------------------------------------------------------------------------------- 1 | build { 2 | sources = [ 3 | "source.nutanix.centos" 4 | ] 5 | 6 | source "nutanix.ubuntu" { 7 | name = "ubuntu" 8 | } 9 | 10 | source "nutanix.centos-kickstart" { 11 | name = "centos-kickstart" 12 | } 13 | 14 | source "nutanix.ubuntu-autoinstall" { 15 | name = "ubuntu-autoinstall" 16 | } 17 | 18 | source "nutanix.windows" { 19 | name = "windows" 20 | } 21 | 22 | provisioner "shell" { 23 | only = ["nutanix.centos", "nutanix.centos-kickstart" ,"nutanix.ubuntu"] 24 | environment_vars = [ 25 | "FOO=hello world", 26 | ] 27 | inline = [ 28 | "echo \"FOO is $FOO\" > example.txt", 29 | ] 30 | } 31 | 32 | provisioner "powershell" { 33 | only = ["nutanix.windows"] 34 | scripts = ["scripts/win-update.ps1"] 35 | pause_before = "2m" 36 | } 37 | provisioner "windows-restart" { 38 | only = ["nutanix.windows"] 39 | restart_timeout = "30m" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /example/windows/files/scripts/EnableWinRMforPacker.ps1: -------------------------------------------------------------------------------- 1 | <# Init Log #> 2 | Start-Transcript -Path 'C:/Automation/setup.txt' -append 3 | Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private 4 | Enable-PSRemoting -Force -SkipNetworkProfileCheck 5 | winrm quickconfig -q 6 | winrm quickconfig -transport:http 7 | winrm set winrm/config '@{MaxTimeoutms="1800000"}' 8 | winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="800"}' 9 | winrm set winrm/config/service '@{AllowUnencrypted="true"}' 10 | winrm set winrm/config/service/auth '@{Basic="true"}' 11 | winrm set winrm/config/client/auth '@{Basic="true"}' 12 | winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port="5985"}' 13 | netsh advfirewall firewall set rule group="Windows Remote Administration" new enable=yes 14 | netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=allow 15 | Set-Service winrm -startuptype "auto" 16 | Restart-Service winrm 17 | Exit 0 -------------------------------------------------------------------------------- /.github/workflows/trivy-scan.yaml: -------------------------------------------------------------------------------- 1 | name: Trivy Scan 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "17 17 * * *" 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | build: 13 | permissions: 14 | contents: read 15 | security-events: write 16 | name: Scan 17 | runs-on: "ubuntu-latest" 18 | steps: 19 | - name: Checkout Code 20 | uses: actions/checkout@v6.0.1 21 | 22 | - name: Run Trivy vulnerability scanner 23 | uses: aquasecurity/trivy-action@0.33.1 24 | env: 25 | TRIVY_DB_REPOSITORY: "ghcr.io/aquasecurity/trivy-db,public.ecr.aws/aquasecurity/trivy-db" 26 | with: 27 | scan-type: "fs" 28 | format: "sarif" 29 | output: "trivy-results.sarif" 30 | severity: "CRITICAL,HIGH" 31 | 32 | - name: Upload Trivy scan results to GitHub Security tab 33 | uses: github/codeql-action/upload-sarif@v4 34 | with: 35 | sarif_file: "trivy-results.sarif" 36 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | # Group all patch and minor Go module updates into a single PR for ease of management. This assumes 9 | # that Go modules respect semver, which is generally true but not guaranteed. 10 | # Update weekly to avoid excessive PRs. 11 | - package-ecosystem: "gomod" 12 | directory: "/" 13 | schedule: 14 | interval: "weekly" 15 | groups: 16 | all-go-mod-patch-and-minor: 17 | patterns: [ "*" ] 18 | update-types: [ "patch", "minor" ] 19 | 20 | # Enable version updates for GitHub Actions 21 | - package-ecosystem: "github-actions" 22 | directory: "/" 23 | schedule: 24 | interval: "daily" 25 | -------------------------------------------------------------------------------- /.github/workflows/synopsys-schedule.yaml: -------------------------------------------------------------------------------- 1 | name: Black Duck Daily Policy Check 2 | on: 3 | schedule: 4 | - cron: "0 0 * * *" 5 | 6 | jobs: 7 | security: 8 | if: github.repository == 'nutanix-cloud-native/packer-plugin-nutanix' 9 | runs-on: ubuntu-latest 10 | permissions: 11 | actions: read 12 | contents: read 13 | security-events: write 14 | checks: write 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v6.0.1 18 | 19 | - name: Setup Go 20 | uses: actions/setup-go@v6 21 | with: 22 | go-version-file: go.mod 23 | 24 | - name: Build Project 25 | run: make build 26 | 27 | - name: Black Duck Full Scan 28 | uses: blackduck-inc/black-duck-security-scan@v2.7.0 29 | with: 30 | blackducksca_url : ${{ secrets.BLACKDUCK_URL }} 31 | blackducksca_token: ${{ secrets.BLACKDUCK_API_TOKEN }} 32 | github_token: ${{ secrets.GITHUB_TOKEN }} 33 | blackducksca_scan_full : true 34 | blackducksca_scan_failure_severities: 'BLOCKER,CRITICAL' -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | example/secret.nutanix.auto.pkrvars.hcl 3 | dist/* 4 | packer-plugin-nutanix 5 | .docs/* 6 | 7 | ### Go ### 8 | # Binaries for programs and plugins 9 | *.exe 10 | *.exe~ 11 | *.dll 12 | *.so 13 | *.dylib 14 | 15 | # Test binary, built with `go test -c` 16 | *.test 17 | 18 | # Output of the go coverage tool, specifically when used with LiteIDE 19 | *.out 20 | 21 | # Dependency directories (remove the comment below to include it) 22 | # vendor/ 23 | 24 | # Go workspace file 25 | go.work 26 | 27 | ### Go Patch ### 28 | /vendor/ 29 | /Godeps/ 30 | 31 | ### macOS ### 32 | # General 33 | .DS_Store 34 | .AppleDouble 35 | .LSOverride 36 | 37 | # Icon must end with two \r 38 | Icon 39 | 40 | 41 | # Thumbnails 42 | ._* 43 | 44 | # Files that might appear in the root of a volume 45 | .DocumentRevisions-V100 46 | .fseventsd 47 | .Spotlight-V100 48 | .TemporaryItems 49 | .Trashes 50 | .VolumeIcon.icns 51 | .com.apple.timemachine.donotpresent 52 | 53 | # Directories potentially created on remote AFP share 54 | .AppleDB 55 | .AppleDesktop 56 | Network Trash Folder 57 | Temporary Items 58 | .apdisk 59 | 60 | ### VisualStudioCode ### 61 | .vscode/* 62 | -------------------------------------------------------------------------------- /example/scripts/cleanup.ps1: -------------------------------------------------------------------------------- 1 | Function Cleanup { 2 | 3 | Clear-Host 4 | 5 | ## Stops the windows update service. 6 | Get-Service -Name wuauserv | Stop-Service -Force -Verbose -ErrorAction SilentlyContinue 7 | 8 | ## Deletes the contents of windows software distribution. 9 | Get-ChildItem "C:\Windows\SoftwareDistribution\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | Remove-Item -Force -Verbose -recurse -ErrorAction SilentlyContinue 10 | 11 | ## Deletes the contents of the Windows Temp folder. 12 | Get-ChildItem "C:\Windows\Temp\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | Remove-Item -Force -Verbose -recurse -ErrorAction SilentlyContinue 13 | 14 | ## Delets all files and folders in user's Temp folder. 15 | Get-ChildItem "C:\users\*\AppData\Local\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item -Force -Verbose -recurse -ErrorAction SilentlyContinue 16 | 17 | ## Remove all files and folders in user's Temporary Internet Files. 18 | Get-ChildItem "C:\users\*\AppData\Local\Microsoft\Windows\Temporary Internet Files\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | Remove-Item -Force -recurse -ErrorAction SilentlyContinue 19 | } 20 | 21 | Cleanup -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NAME=nutanix 2 | BINARY=packer-plugin-${NAME} 3 | PLUGIN_FQN="$(shell grep -E '^module' 2 | 3 | - `ip_wait_timeout` (duration string | ex: "1h5m2s") - Amount of time to wait for VM's IP, similar to 'ssh_timeout'. 4 | Defaults to `30m` (30 minutes). Refer to the Golang 5 | [ParseDuration](https://golang.org/pkg/time/#ParseDuration) 6 | documentation for full details. 7 | 8 | - `ip_settle_timeout` (duration string | ex: "1h5m2s") - Amount of time to wait for VM's IP to settle down, sometimes VM may 9 | report incorrect IP initially, then it is recommended to set that 10 | parameter to apx. 2 minutes. Examples `45s` and `10m`. 11 | Defaults to `5s` (5 seconds). Refer to the Golang 12 | [ParseDuration](https://golang.org/pkg/time/#ParseDuration) 13 | documentation for full details. 14 | 15 | - `ip_wait_address` (\*string) - Set this to a CIDR address to cause the service to wait for an address that is contained in 16 | this network range. Defaults to `0.0.0.0/0` for any IPv4 address. Examples include: 17 | 18 | * empty string ("") - remove all filters 19 | * `0:0:0:0:0:0:0:0/0` - allow only ipv6 addresses 20 | * `192.168.1.0/24` - only allow ipv4 addresses from 192.168.1.1 to 192.168.1.254 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/workflows/test-plugin-example.yml: -------------------------------------------------------------------------------- 1 | # This is a manually triggered action workflow. 2 | # It uses Packer at latest version to init, validate and build 3 | # an example configuration in a folder. 4 | # This action is compatible with Packer v1.7.0 or later. 5 | name: test plugin example 6 | 7 | on: 8 | workflow_dispatch: 9 | inputs: 10 | logs: 11 | description: 'Set 1 to activate full logs' 12 | required: false 13 | default: '0' 14 | folder: 15 | description: 'Example folder' 16 | required: false 17 | default: './example' 18 | 19 | jobs: 20 | build: 21 | runs-on: ubuntu-latest 22 | name: init and build example 23 | steps: 24 | - name: Checkout Repository 25 | uses: actions/checkout@v6.0.1 26 | 27 | - name: Init 28 | uses: hashicorp/packer-github-actions@master 29 | with: 30 | working_directory: ${{ github.event.inputs.folder }} 31 | command: init 32 | 33 | - name: Validate 34 | uses: hashicorp/packer-github-actions@master 35 | with: 36 | working_directory: ${{ github.event.inputs.folder }} 37 | command: validate 38 | env: 39 | PACKER_LOG: ${{ github.event.inputs.logs }} 40 | 41 | - name: Build 42 | uses: hashicorp/packer-github-actions@master 43 | with: 44 | working_directory: ${{ github.event.inputs.folder }} 45 | command: build 46 | env: 47 | PACKER_LOG: ${{ github.event.inputs.logs }} -------------------------------------------------------------------------------- /example/scripts/ks.cfg: -------------------------------------------------------------------------------- 1 | # Author: Tomasz Filipiec 2 | # Desc.: Simple kickstart file for automated installation 3 | # OS: CentOS 7 Minimal (core) 4 | # Version: 1.0 5 | 6 | # Turning on text-mode installation (little quicker than GUI) 7 | text 8 | 9 | # Setting up authentication and keyboard 10 | auth --enableshadow --passalgo=sha512 11 | keyboard --vckeymap=us --xlayouts='us' 12 | 13 | # Installation files source (CentOS-7.0-1406-x86_64-Minimal.iso) 14 | cdrom 15 | 16 | # Using only primary disk, ignoring others 17 | ignoredisk --only-use=sda 18 | 19 | # Setting up language to English 20 | lang en-US.UTF-8 21 | 22 | # Setting up network interface to DHCP 23 | network --bootproto=dhcp --ipv6=auto --hostname=centos-ks.local --activate 24 | 25 | # Root password (remember that plaintext only for information purposes) 26 | rootpw --plaintext --allow-ssh packer 27 | 28 | 29 | # Setting up firewall and enabling SSH for remote management 30 | firewall --enabled --service=ssh 31 | 32 | # Setting timezone 33 | timezone Europe/Berlin --isUtc 34 | 35 | # Setting up Security-Enhanced Linux into enforcing 36 | selinux --enforcing 37 | 38 | # Setting up MBR 39 | bootloader --location=mbr --boot-drive=sda 40 | 41 | # Setting up Logical Volume Manager and autopartitioning 42 | clearpart --all --drives=sda --initlabel 43 | autopart --type=lvm 44 | 45 | # Eject cdrom and reboot 46 | reboot --eject 47 | 48 | # Installing only packages for minimal install 49 | %packages 50 | @Core 51 | chrony 52 | %end -------------------------------------------------------------------------------- /test/e2e/centos-iso/scripts/ks.cfg: -------------------------------------------------------------------------------- 1 | # Author: Tomasz Filipiec 2 | # Desc.: Simple kickstart file for automated installation 3 | # OS: CentOS 7 Minimal (core) 4 | # Version: 1.0 5 | 6 | # Turning on text-mode installation (little quicker than GUI) 7 | text 8 | 9 | # Setting up authentication and keyboard 10 | auth --enableshadow --passalgo=sha512 11 | keyboard --vckeymap=us --xlayouts='us' 12 | 13 | # Installation files source (CentOS-7.0-1406-x86_64-Minimal.iso) 14 | cdrom 15 | 16 | # Using only primary disk, ignoring others 17 | ignoredisk --only-use=sda 18 | 19 | # Setting up language to English 20 | lang en-US.UTF-8 21 | 22 | # Setting up network interface to DHCP 23 | network --bootproto=dhcp --ipv6=auto --hostname=centos-ks.local --activate 24 | 25 | # Root password (remember that plaintext only for information purposes) 26 | rootpw --plaintext packer 27 | 28 | # Setting up firewall and enabling SSH for remote management 29 | firewall --enabled --service=ssh 30 | 31 | # Setting timezone 32 | timezone Europe/Berlin --isUtc 33 | 34 | # Setting up Security-Enhanced Linux into enforcing 35 | selinux --enforcing 36 | 37 | # Setting up MBR 38 | bootloader --location=mbr --boot-drive=sda 39 | 40 | # Setting up Logical Volume Manager and autopartitioning 41 | clearpart --all --drives=sda,sdb --initlabel 42 | ignoredisk --only-use=sda,sdb 43 | autopart --type=lvm 44 | 45 | # Eject cdrom and reboot 46 | reboot --eject 47 | 48 | # Installing only packages for minimal install 49 | %packages 50 | @Core 51 | chrony 52 | %end -------------------------------------------------------------------------------- /test/e2e/centos-img/source.pkr.hcl: -------------------------------------------------------------------------------- 1 | source "nutanix" "centos" { 2 | nutanix_username = var.nutanix_username 3 | nutanix_password = var.nutanix_password 4 | nutanix_endpoint = var.nutanix_endpoint 5 | nutanix_port = var.nutanix_port 6 | nutanix_insecure = var.nutanix_insecure 7 | cluster_name = var.nutanix_cluster 8 | os_type = "Linux" 9 | 10 | vm_disks { 11 | image_type = "DISK_IMAGE" 12 | source_image_uri = "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-2111.qcow2" 13 | source_image_checksum = "4c34278cd7ba51e47d864a5cb34301a2ec7853786cb73877f3fe61bb1040edd4" 14 | source_image_checksum_type = "sha256" 15 | disk_size_gb = 20 16 | } 17 | 18 | vm_nics { 19 | subnet_name = var.nutanix_subnet 20 | } 21 | 22 | image_categories { 23 | key = "TemplateType" 24 | value = "Vm" 25 | } 26 | 27 | vm_categories { 28 | key = "Environment" 29 | value = "Testing" 30 | } 31 | 32 | vm_name = "e2e-packer-${var.test}-${formatdate("MDYYhms", timestamp())}" 33 | 34 | image_name = "e2e-packer-${var.test}-${formatdate("MDYYhms", timestamp())}" 35 | image_delete = true 36 | 37 | force_deregister = true 38 | user_data = "I2Nsb3VkLWNvbmZpZwp1c2VyczoKICAtIG5hbWU6IGNlbnRvcwogICAgc3VkbzogWydBTEw9KEFMTCkgTk9QQVNTV0Q6QUxMJ10KY2hwYXNzd2Q6CiAgbGlzdDogfAogICAgY2VudG9zOnBhY2tlcgogIGV4cGlyZTogRmFsc2UKc3NoX3B3YXV0aDogVHJ1ZQ==" 39 | 40 | shutdown_command = "echo 'packer' | sudo -S shutdown -P now" 41 | shutdown_timeout = "2m" 42 | ssh_password = "packer" 43 | ssh_username = "centos" 44 | } 45 | -------------------------------------------------------------------------------- /test/e2e/centos-iso/source.pkr.hcl: -------------------------------------------------------------------------------- 1 | source "nutanix" "centos" { 2 | nutanix_username = var.nutanix_username 3 | nutanix_password = var.nutanix_password 4 | nutanix_endpoint = var.nutanix_endpoint 5 | nutanix_port = var.nutanix_port 6 | nutanix_insecure = var.nutanix_insecure 7 | cluster_name = var.nutanix_cluster 8 | os_type = "Linux" 9 | 10 | vm_disks { 11 | image_type = "ISO_IMAGE" 12 | source_image_uri = "https://vault.centos.org/7.9.2009/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso" 13 | source_image_checksum = "07b94e6b1a0b0260b94c83d6bb76b26bf7a310dc78d7a9c7432809fb9bc6194a" 14 | source_image_checksum_type = "sha256" 15 | } 16 | 17 | vm_disks { 18 | image_type = "DISK" 19 | disk_size_gb = 40 20 | } 21 | 22 | vm_disks { 23 | image_type = "DISK" 24 | disk_size_gb = 20 25 | } 26 | 27 | vm_nics { 28 | subnet_name = var.nutanix_subnet 29 | } 30 | 31 | image_categories { 32 | key = "TemplateType" 33 | value = "Vm" 34 | } 35 | 36 | vm_categories { 37 | key = "Environment" 38 | value = "Testing" 39 | } 40 | 41 | cd_files = ["scripts/ks.cfg"] 42 | cd_label = "OEMDRV" 43 | 44 | vm_name = "e2e-packer-${var.test}-${formatdate("MDYYhms", timestamp())}" 45 | image_name = "e2e-packer-${var.test}-${formatdate("MDYYhms", timestamp())}" 46 | image_delete = true 47 | 48 | boot_priority = "disk" 49 | 50 | force_deregister = true 51 | 52 | shutdown_command = "echo 'packer' | sudo -S shutdown -P now" 53 | shutdown_timeout = "2m" 54 | ssh_password = "packer" 55 | ssh_username = "root" 56 | } 57 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | 2 | name: "Code Scanning - Action" 3 | 4 | on: 5 | push: 6 | branches: [main] 7 | pull_request: 8 | branches: [main] 9 | schedule: 10 | - cron: '30 1 * * 0' 11 | 12 | jobs: 13 | CodeQL-Build: 14 | runs-on: ubuntu-latest 15 | 16 | permissions: 17 | # required for all workflows 18 | security-events: write 19 | 20 | # only required for workflows in private repositories 21 | actions: read 22 | contents: read 23 | 24 | steps: 25 | - name: Checkout repository 26 | uses: actions/checkout@v6.0.1 27 | 28 | # Initializes the CodeQL tools for scanning. 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v4 31 | # Override language selection by uncommenting this and choosing your languages 32 | # with: 33 | # languages: go, javascript, csharp, python, cpp, java 34 | 35 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 36 | # If this step fails, then you should remove it and run the build manually (see below). 37 | - name: Autobuild 38 | uses: github/codeql-action/autobuild@v4 39 | 40 | # ℹ️ Command-line programs to run using the OS shell. 41 | # 📚 https://git.io/JvXDl 42 | 43 | # ✏️ If the Autobuild fails above, remove it and uncomment the following 44 | # three lines and modify them (or add more) to build your code if your 45 | # project uses a compiled language 46 | 47 | #- run: | 48 | # make bootstrap 49 | # make release 50 | 51 | - name: Perform CodeQL Analysis 52 | uses: github/codeql-action/analyze@v4 53 | -------------------------------------------------------------------------------- /.github/workflows/integration.yml: -------------------------------------------------------------------------------- 1 | name: Integration 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | check: 9 | name: Check 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout Code 13 | uses: actions/checkout@v6.0.1 14 | 15 | - name: Setup Go 16 | uses: actions/setup-go@v6 17 | with: 18 | go-version-file: go.mod 19 | 20 | - name: Static Check 21 | uses: dominikh/staticcheck-action@v1.4.0 22 | with: 23 | version: "latest" 24 | install-go: false 25 | 26 | vet: 27 | name: Vet 28 | runs-on: ubuntu-latest 29 | steps: 30 | - name: Checkout Code 31 | uses: actions/checkout@v6.0.1 32 | 33 | - name: Setup Go 34 | uses: actions/setup-go@v6 35 | with: 36 | go-version-file: go.mod 37 | 38 | - name: Vet Go code 39 | run: go vet ./... 40 | 41 | build: 42 | name: Build 43 | runs-on: ubuntu-latest 44 | steps: 45 | - name: Check out code 46 | uses: actions/checkout@v6.0.1 47 | 48 | - name: Set up Go 49 | uses: actions/setup-go@v6 50 | with: 51 | go-version-file: go.mod 52 | 53 | - name: Compile 54 | run: make build 55 | 56 | - name: Trivy scan 57 | uses: aquasecurity/trivy-action@0.33.1 58 | env: 59 | TRIVY_DB_REPOSITORY: "ghcr.io/aquasecurity/trivy-db,public.ecr.aws/aquasecurity/trivy-db" 60 | with: 61 | scan-type: "fs" 62 | ignore-unfixed: true 63 | format: "table" 64 | exit-code: "1" 65 | vuln-type: "os,library" 66 | severity: "CRITICAL,HIGH" 67 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | **What this PR does / why we need it**: 10 | 11 | **Which issue(s) this PR fixes** *(optional, in `fixes #(, fixes #, ...)` format, will close the issue(s) when PR gets merged)*: 12 | Fixes # 13 | 14 | **How Has This Been Tested?**: 15 | 16 | _Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration and test output_ 17 | 18 | 19 | **Special notes for your reviewer**: 20 | 21 | _Please confirm that if this PR changes any image versions, then that's the sole change this PR makes._ 22 | 23 | **Release note**: 24 | 28 | ```release-note 29 | 30 | ``` 31 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This GitHub action can publish assets for release when a tag is created. 2 | # Currently its setup to run on any tag that matches the pattern "v*" (ie. v0.1.0). 3 | # 4 | # This uses an action (hashicorp/ghaction-import-gpg) that assumes you set your 5 | # private key in the `GPG_PRIVATE_KEY` secret and passphrase in the `GPG_PASSPHRASE` 6 | # secret. If you would rather own your own GPG handling, please fork this action 7 | # or use an alternative one for key handling. 8 | # 9 | # You will need to pass the `--batch` flag to `gpg` in your signing step 10 | # in `goreleaser` to indicate this is being used in a non-interactive mode. 11 | # 12 | name: Release 13 | on: 14 | push: 15 | tags: 16 | - "v*" 17 | 18 | jobs: 19 | goreleaser: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v6.0.1 24 | with: 25 | fetch-depth: 0 26 | 27 | - name: Set up Go 28 | uses: actions/setup-go@v6 29 | with: 30 | go-version-file: go.mod 31 | 32 | - name: Describe plugin 33 | id: plugin_describe 34 | run: echo "::set-output name=api_version::$(go run . describe | jq -r '.api_version')" 35 | 36 | - name: Import GPG key 37 | id: import_gpg 38 | uses: crazy-max/ghaction-import-gpg@v6 39 | with: 40 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} 41 | passphrase: ${{ secrets.GPG_PASSPHRASE }} 42 | 43 | - name: Run GoReleaser 44 | uses: goreleaser/goreleaser-action@v6 45 | with: 46 | version: '~> v2' 47 | args: release --clean 48 | env: 49 | GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | API_VERSION: ${{ steps.plugin_describe.outputs.api_version }} 52 | -------------------------------------------------------------------------------- /example/windows/README.md: -------------------------------------------------------------------------------- 1 | # Windows 11 Template Creation on Nutanix using Packer 2 | 3 | This Packer template automates the creation of a Windows 11 VM template on a Nutanix cluster. The process configures the VM and performs several actions to ensure a complete and automated setup. 4 | 5 | ## Actions Performed 6 | 7 | - **Create the VM** 8 | - Allocate 1 vCPU, 4 cores, and 8192 MB of memory. 9 | - Deploy the VM on the specified Nutanix cluster. 10 | 11 | - **Enable Security Features** 12 | - Turn on Secure Boot. 13 | - Add a virtual TPM (vTPM). 14 | - Enable Credential Guard via `hardware_virtualization`. 15 | 16 | - **Attach Networking** 17 | - Connect a NIC to the specified Nutanix subnet. 18 | 19 | - **Configure Boot Media** 20 | - Attach a CD-ROM with a stock Windows 11 ISO. 21 | - Attach a second CD-ROM with the Nutanix VirtIO ISO for drivers. 22 | 23 | - **Attach Storage** 24 | - Add a 60 GB disk on the specified storage container. 25 | 26 | - **Set Boot Priority** 27 | - Configure the VM to boot from CD-ROM. 28 | - Wait 10 seconds after initial boot (depending on your hardware, this value may need to be adjusted). 29 | - Send keyboard input to bypass the "Press any key to boot from CD or DVD" prompt. 30 | 31 | - **Automate the Installation** 32 | - Use `autounattend.xml` to: 33 | - Install Windows automatically. 34 | - Load VirtIO drivers from the attached ISO. 35 | - Run `SetupComplete.cmd` to perform post-install tasks (e.g., enable WinRM). 36 | 37 | - **Connect for Provisioning** 38 | - Use WinRM on port 5985. 39 | - Set the connection timeout to 30 minutes. 40 | 41 | - **Clean Up** 42 | - Detach all CD-ROMs after the build completes. 43 | 44 | - **Finalize the Build** 45 | - Do **not** create a Nutanix image. 46 | - Retain the VM for further testing or manual modifications. 47 | - Create a Nutanix template from the built VM with the specified name and description. 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are always welcome. Before contributing please search the [issue tracker](../../issues). Your issue may have already been discussed or fixed in `main`. To contribute, [fork](https://help.github.com/articles/fork-a-repo/) this repository, commit your changes, and [send a Pull Request](https://help.github.com/articles/using-pull-requests/). 4 | 5 | ## Feature requests 6 | 7 | Feature requests should be submitted in the [issue tracker](../../issues), with a description of the expected behavior & use case, where they'll remain closed until sufficient interest, [e.g. :+1: reactions](https://help.github.com/articles/about-discussions-in-issues-and-pull-requests/), has been [shown by the community](../../issues?q=label%3A%22votes+needed%22+sort%3Areactions-%2B1-desc). 8 | 9 | Before submitting an issue, please search for similar ones in the [closed issues](../../issues?q=is%3Aissue+is%3Aclosed+label%3Aenhancement). 10 | 11 | ## Pull requests 12 | 13 | ### Approval and release process 14 | 15 | Pull requests approvals go through the following steps: 16 | 17 | 1. A GitHub action may be triggered to lint and test. 18 | 2. A maintainer reviews the changes. Any change requires at least one review. 19 | 3. The pull request can be merged when at least one maintainer approves it. 20 | 21 | ## Contributor License Agreement 22 | 23 | Before you submit your pull request, you'll need to sign the [Nutanix Contributor License Agreement (CLA)](https://www.nutanix.dev/cla/). The CLA must be agreed to by all contributors who are not Nutanix Full-time Employees (FTE) or interns prior to the contribution being merged into the project codebase. The CLA is substantially similar to the Apache Contributor License Agreement, which is the industry standard CLA. 24 | 25 | For more information about CLAs, please check out Alex Russell's excellent post, 26 | ["Why Do I Need to Sign This?"](https://infrequently.org/2008/06/why-do-i-need-to-sign-this/). -------------------------------------------------------------------------------- /example/windows/source.nutanix.pkr.hcl: -------------------------------------------------------------------------------- 1 | 2 | 3 | source "nutanix" "windows11" { 4 | nutanix_username = var.nutanix_username 5 | nutanix_password = var.nutanix_password 6 | nutanix_endpoint = var.nutanix_endpoint 7 | nutanix_port = var.nutanix_port 8 | nutanix_insecure = var.nutanix_insecure 9 | cluster_name = var.nutanix_cluster 10 | os_type = "Windows" 11 | communicator = "winrm" 12 | cpu = 1 13 | core = 4 14 | memory_mb = 8192 15 | boot_type = "secure_boot" 16 | boot_priority = "cdrom" 17 | boot_wait = "10s" 18 | boot_command = [ 19 | "" 20 | ] 21 | vtpm { 22 | enabled = true 23 | } 24 | hardware_virtualization = true 25 | vm_disks { 26 | image_type = "ISO_IMAGE" 27 | source_image_name = var.windows_11_iso_image_name 28 | } 29 | vm_disks { 30 | image_type = "ISO_IMAGE" 31 | source_image_name = "Nutanix-VirtIO-1.2.4.iso" 32 | } 33 | vm_disks { 34 | image_type = "DISK" 35 | disk_size_gb = 60 36 | storage_container_uuid = var.nutanix_storage_container_uuid 37 | } 38 | vm_nics { 39 | subnet_name = var.nutanix_subnet 40 | } 41 | cd_files = [ 42 | "files/autounattend.xml", 43 | "files/scripts/EnableWinRMforPacker.ps1", 44 | "files/scripts/SetupComplete.cmd" 45 | ] 46 | image_skip = true 47 | vm_retain = true 48 | vm_clean { 49 | cdrom = true 50 | } 51 | template { 52 | create = true 53 | name = "Windows-11-Template-{{isotime}}" 54 | description = "Windows 11 Template Created by Packer" 55 | } 56 | winrm_port = 5985 57 | winrm_timeout = "30m" 58 | winrm_use_ssl = false 59 | winrm_username = var.winrm_username 60 | winrm_password = var.winrm_password 61 | } 62 | 63 | -------------------------------------------------------------------------------- /.github/workflows/notify-integration-release-via-manual.yaml: -------------------------------------------------------------------------------- 1 | # Manual release workflow is used for deploying documentation updates 2 | # on the specified branch without making an official plugin release. 3 | name: Notify Integration Release (Manual) 4 | on: 5 | workflow_dispatch: 6 | inputs: 7 | version: 8 | description: "The release version (semver)" 9 | default: 1.0.0 10 | required: false 11 | branch: 12 | description: "A branch or SHA" 13 | default: 'main' 14 | required: false 15 | jobs: 16 | notify-release: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout this repo 20 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.1 21 | with: 22 | ref: ${{ github.event.inputs.branch }} 23 | # Ensure that Docs are Compiled 24 | - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 25 | - shell: bash 26 | run: make generate 27 | - shell: bash 28 | run: | 29 | if [[ -z "$(git status -s)" ]]; then 30 | echo "OK" 31 | else 32 | echo "Docs have been updated, but the compiled docs have not been committed." 33 | echo "Run 'make generate', and commit the result to resolve this error." 34 | exit 1 35 | fi 36 | # Perform the Release 37 | - name: Checkout integration-release-action 38 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.1 39 | with: 40 | repository: hashicorp/integration-release-action 41 | path: ./integration-release-action 42 | - name: Notify Release 43 | uses: ./integration-release-action 44 | with: 45 | # The integration identifier will be used by the Packer team to register the integration 46 | # the expected format is packer// 47 | integration_identifier: "packer/nutanix-cloud-native/nutanix" 48 | release_version: ${{ github.event.inputs.version }} 49 | release_sha: ${{ github.event.inputs.branch }} 50 | github_token: ${{ secrets.GITHUB_TOKEN }} 51 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 2 | The `Nutanix` multi-component plugin can be used with HashiCorp [Packer](https://www.packer.io) to create custom images. 3 | 4 | ### Installation 5 | 6 | To install this plugin, copy and paste this code into your Packer configuration, then run [`packer init`](https://www.packer.io/docs/commands/init). 7 | 8 | ``` 9 | packer { 10 | required_plugins { 11 | nutanix = { 12 | version = ">= 1.1.4" 13 | source = "github.com/nutanix-cloud-native/nutanix" 14 | } 15 | } 16 | } 17 | ``` 18 | 19 | Alternatively, you can use `packer plugins install` to manage installation of this plugin. 20 | 21 | ```sh 22 | $ packer plugins install github.com/nutanix-cloud-native/nutanix 23 | ``` 24 | 25 | ### Components 26 | 27 | #### Builders 28 | 29 | - [nutanix](/packer/integrations/nutanix-cloud-native/nutanix/latest/components/builder/nutanix) - The Nutanix builder will create a temporary VM as foundation of your Packer image, apply all providers you define to customize your image, then clone the VM disk image as your final Packer image. 30 | 31 | ### Limitations 32 | #### Building temporary ISOs on MacOS 33 | If you want to use the `cd_files` option to create an additional ISO image for kickstart files or similar purposes, be aware that macOS does not generate a compatible file by default. 34 | To enable support on macOS, please install xorriso. 35 | ``` 36 | brew install xorriso 37 | ``` 38 | 39 | ### Contributing 40 | See the [contributing docs](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/blob/main/CONTRIBUTING.md). 41 | 42 | ### Support 43 | #### Community Plus 44 | 45 | This code is developed in the open with input from the community through issues and PRs. A Nutanix engineering team serves as the maintainer. Documentation is available in the project repository. 46 | 47 | Issues and enhancement requests can be submitted in the [Issues tab of this repository](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/issues). Please search for and review the existing open issues before submitting a new issue. 48 | 49 | ### License 50 | The project is released under version 2.0 of the [Apache license](http://www.apache.org/licenses/LICENSE-2.0). 51 | 52 | -------------------------------------------------------------------------------- /.web-docs/README.md: -------------------------------------------------------------------------------- 1 | 2 | The `Nutanix` multi-component plugin can be used with HashiCorp [Packer](https://www.packer.io) to create custom images. 3 | 4 | ### Installation 5 | 6 | To install this plugin, copy and paste this code into your Packer configuration, then run [`packer init`](https://www.packer.io/docs/commands/init). 7 | 8 | ``` 9 | packer { 10 | required_plugins { 11 | nutanix = { 12 | version = ">= 1.1.4" 13 | source = "github.com/nutanix-cloud-native/nutanix" 14 | } 15 | } 16 | } 17 | ``` 18 | 19 | Alternatively, you can use `packer plugins install` to manage installation of this plugin. 20 | 21 | ```sh 22 | $ packer plugins install github.com/nutanix-cloud-native/nutanix 23 | ``` 24 | 25 | ### Components 26 | 27 | #### Builders 28 | 29 | - [nutanix](/packer/integrations/nutanix-cloud-native/nutanix/latest/components/builder/nutanix) - The Nutanix builder will create a temporary VM as foundation of your Packer image, apply all providers you define to customize your image, then clone the VM disk image as your final Packer image. 30 | 31 | ### Limitations 32 | #### Building temporary ISOs on MacOS 33 | If you want to use the `cd_files` option to create an additional ISO image for kickstart files or similar purposes, be aware that macOS does not generate a compatible file by default. 34 | To enable support on macOS, please install xorriso. 35 | ``` 36 | brew install xorriso 37 | ``` 38 | 39 | ### Contributing 40 | See the [contributing docs](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/blob/main/CONTRIBUTING.md). 41 | 42 | ### Support 43 | #### Community Plus 44 | 45 | This code is developed in the open with input from the community through issues and PRs. A Nutanix engineering team serves as the maintainer. Documentation is available in the project repository. 46 | 47 | Issues and enhancement requests can be submitted in the [Issues tab of this repository](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/issues). Please search for and review the existing open issues before submitting a new issue. 48 | 49 | ### License 50 | The project is released under version 2.0 of the [Apache license](http://www.apache.org/licenses/LICENSE-2.0). 51 | 52 | -------------------------------------------------------------------------------- /.github/workflows/notify-integration-release-via-tag.yaml: -------------------------------------------------------------------------------- 1 | name: Notify Integration Release (Tag) 2 | on: 3 | push: 4 | tags: 5 | - '*.*.*' # Proper releases 6 | jobs: 7 | strip-version: 8 | runs-on: ubuntu-latest 9 | outputs: 10 | packer-version: ${{ steps.strip.outputs.packer-version }} 11 | steps: 12 | - name: Strip leading v from version tag 13 | id: strip 14 | env: 15 | REF: ${{ github.ref_name }} 16 | run: | 17 | echo "packer-version=$(echo "$REF" | sed -E 's/v?([0-9]+\.[0-9]+\.[0-9]+)/\1/')" >> "$GITHUB_OUTPUT" 18 | notify-release: 19 | needs: 20 | - strip-version 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Checkout this repo 24 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.1 25 | with: 26 | ref: ${{ github.ref }} 27 | # Ensure that Docs are Compiled 28 | - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 29 | - shell: bash 30 | run: make generate 31 | - shell: bash 32 | run: | 33 | if [[ -z "$(git status -s)" ]]; then 34 | echo "OK" 35 | else 36 | echo "Docs have been updated, but the compiled docs have not been committed." 37 | echo "Run 'make generate', and commit the result to resolve this error." 38 | exit 1 39 | fi 40 | # Perform the Release 41 | - name: Checkout integration-release-action 42 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.1 43 | with: 44 | repository: hashicorp/integration-release-action 45 | path: ./integration-release-action 46 | - name: Notify Release 47 | uses: ./integration-release-action 48 | with: 49 | # The integration identifier will be used by the Packer team to register the integration 50 | # the expected format is packer// 51 | integration_identifier: "packer/nutanix-cloud-native/nutanix" 52 | release_version: ${{ needs.strip-version.outputs.packer-version }} 53 | release_sha: ${{ github.ref }} 54 | github_token: ${{ secrets.GITHUB_TOKEN }} 55 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | # Make sure to check the documentation at http://goreleaser.com 3 | env: 4 | - CGO_ENABLED=0 5 | before: 6 | hooks: 7 | # We strongly recommend running tests to catch any regression before release. 8 | # Even though, this an optional step. 9 | - go test ./... 10 | # As part of the release doc files are included as a separate deliverable for 11 | # consumption by Packer.io. To include a separate docs.zip uncomment the following command. 12 | # - make ci-release-docs 13 | # Check plugin compatibility with required version of the Packer SDK 14 | - make plugin-check 15 | builds: 16 | # A separated build to run the packer-plugins-check only once for a linux_amd64 binary 17 | - id: plugin-check 18 | mod_timestamp: "{{ .CommitTimestamp }}" 19 | flags: 20 | - -trimpath #removes all file system paths from the compiled executable 21 | ldflags: 22 | - "-s -w -X {{ .ModulePath }}/version.Version={{.Version}} -X {{ .ModulePath }}/version.VersionPrerelease= " 23 | goos: 24 | - linux 25 | goarch: 26 | - amd64 27 | binary: "{{ .ProjectName }}_v{{ .Version }}_{{ .Env.API_VERSION }}_{{ .Os }}_{{ .Arch }}" 28 | - mod_timestamp: "{{ .CommitTimestamp }}" 29 | flags: 30 | - -trimpath #removes all file system paths from the compiled executable 31 | ldflags: 32 | - "-s -w -X {{ .ModulePath }}/version.Version={{.Version}} -X {{ .ModulePath }}/version.VersionPrerelease= " 33 | goos: 34 | - netbsd 35 | - solaris 36 | - openbsd 37 | - freebsd 38 | - windows 39 | - linux 40 | - darwin 41 | goarch: 42 | - amd64 43 | - "386" 44 | - arm 45 | - arm64 46 | ignore: 47 | - goos: openbsd 48 | goarch: arm64 49 | - goos: darwin 50 | goarch: "386" 51 | - goos: linux 52 | goarch: amd64 53 | binary: "{{ .ProjectName }}_v{{ .Version }}_{{ .Env.API_VERSION }}_{{ .Os }}_{{ .Arch }}" 54 | archives: 55 | - formats: ["zip"] 56 | files: 57 | - none* 58 | name_template: "{{ .ProjectName }}_v{{ .Version }}_{{ .Env.API_VERSION }}_{{ .Os }}_{{ .Arch }}" 59 | checksum: 60 | name_template: "{{ .ProjectName }}_v{{ .Version }}_SHA256SUMS" 61 | algorithm: sha256 62 | signs: 63 | - artifacts: checksum 64 | args: 65 | # if you are using this is in a GitHub action or some other automated pipeline, you 66 | # need to pass the batch flag to indicate its not interactive. 67 | - "--batch" 68 | - "--local-user" 69 | - "{{ .Env.GPG_FINGERPRINT }}" 70 | - "--output" 71 | - "${signature}" 72 | - "--detach-sign" 73 | - "${artifact}" 74 | release: 75 | # If you want to manually examine the release before its live, uncomment this line: 76 | # draft: true 77 | # As part of the release doc files are included as a separate deliverable for consumption by Packer.io. 78 | # To include a separate docs.zip uncomment the extra_files config and the docs.zip command hook above. 79 | # extra_files: 80 | # - glob: ./docs.zip 81 | 82 | changelog: 83 | disable: true 84 | -------------------------------------------------------------------------------- /.github/workflows/test-plugin-e2e.yaml: -------------------------------------------------------------------------------- 1 | name: E2E tests 2 | 3 | on: 4 | pull_request: 5 | workflow_dispatch: 6 | inputs: 7 | logs: 8 | description: "Set 1 to activate full logs" 9 | required: false 10 | default: "0" 11 | 12 | jobs: 13 | plugin-build: 14 | runs-on: [self-hosted, nxlab, packer] 15 | outputs: 16 | test-list: ${{ steps.test-list.outputs.list}} 17 | 18 | steps: 19 | - name: Checkout Repository 20 | uses: actions/checkout@v6.0.1 21 | 22 | - name: Setup `golang` 23 | uses: actions/setup-go@v6 24 | with: 25 | go-version-file: go.mod 26 | 27 | - name: Build packer plugin 28 | run: | 29 | cd $GITHUB_WORKSPACE 30 | make build 31 | 32 | - uses: actions/upload-artifact@v6 33 | with: 34 | name: packer-plugin-nutanix 35 | path: packer-plugin-nutanix 36 | retention-days: 7 37 | 38 | - name: build test list 39 | id: test-list 40 | run: echo "list=$(ls test/e2e | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT 41 | 42 | e2e: 43 | name: E2E test 44 | needs: plugin-build 45 | 46 | strategy: 47 | matrix: 48 | test: ${{fromJSON(needs.plugin-build.outputs.test-list)}} 49 | 50 | runs-on: [self-hosted, nxlab, packer] 51 | defaults: 52 | run: 53 | working-directory: test/e2e/${{ matrix.test}} 54 | 55 | steps: 56 | - name: Checkout Repository 57 | uses: actions/checkout@v6.0.1 58 | 59 | - name: Setup `packer` 60 | uses: hashicorp/setup-packer@main 61 | id: setup-packer 62 | 63 | - name: Setup `xorriso` 64 | run: | 65 | sudo apt update -y 66 | sudo apt install -y xorriso 67 | 68 | - uses: actions/download-artifact@v7 69 | with: 70 | name: packer-plugin-nutanix 71 | path: /tmp 72 | 73 | - name: Fix plugin permissions 74 | run: | 75 | chmod +x /tmp/packer-plugin-nutanix 76 | 77 | - name: Install plugin 78 | run: | 79 | packer plugins install --path /tmp/packer-plugin-nutanix "github.com/nutanix-cloud-native/nutanix" 80 | 81 | - name: Run `packer init` 82 | id: init 83 | run: | 84 | packer init . 85 | 86 | - name: Run `packer validate` 87 | id: validate 88 | run: packer validate -var "test=${{ matrix.test}}" . 89 | env: 90 | PACKER_LOG: ${{ github.event.inputs.logs }} 91 | 92 | - name: Run `packer build` 93 | id: build 94 | run: packer build -var "test=${{ matrix.test}}" . 95 | env: 96 | PACKER_LOG: ${{ github.event.inputs.logs }} 97 | 98 | results: 99 | if: ${{ always() }} 100 | runs-on: [self-hosted, nxlab, packer] 101 | name: Final E2E results 102 | needs: [e2e] 103 | steps: 104 | - run: | 105 | result="${{ needs.e2e.result }}" 106 | if [[ $result == "success" || $result == "skipped" ]]; then 107 | exit 0 108 | else 109 | exit 1 110 | fi 111 | -------------------------------------------------------------------------------- /.github/workflows/synopsys.yaml: -------------------------------------------------------------------------------- 1 | name: Black Duck Policy Check 2 | on: 3 | pull_request: 4 | pull_request_target: 5 | branches: 6 | - main 7 | push: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | check_approvals: 13 | runs-on: ubuntu-latest 14 | # Run this job only if the following conditions are met: 15 | # 1. The pull request has the 'integration-test' label. 16 | # 2. The event is either: 17 | # a. A 'pull_request' event where the base and head repositories are the same (internal PR). 18 | # b. A 'pull_request_target' event where the base and head repositories are different (external PR). 19 | if: ${{ contains(github.event.pull_request.labels.*.name, 'integration-test') && 20 | (( github.event_name == 'pull_request' && github.event.pull_request.base.repo.clone_url == github.event.pull_request.head.repo.clone_url) || 21 | (github.event_name == 'pull_request_target' && github.event.pull_request.base.repo.clone_url != github.event.pull_request.head.repo.clone_url )) }} 22 | outputs: 23 | # Output the approval status for pull_request_target events, otherwise default to 'true' 24 | check_approvals: ${{ github.event_name == 'pull_request_target' && steps.check_approvals.outputs.check_approvals || 'true' }} 25 | # Output whether the PR is external 26 | external_pr: ${{ github.event.pull_request.base.repo.clone_url != github.event.pull_request.head.repo.clone_url }} 27 | steps: 28 | - name: Check integration test allowance status 29 | # Only run this step for pull_request_target events 30 | if: ${{ github.event_name == 'pull_request_target' }} 31 | id: check_approvals 32 | # Use an external action to check if the PR has the necessary approvals 33 | uses: nutanix-cloud-native/action-check-approvals@v1 34 | security: 35 | needs: check_approvals 36 | if: ${{ (github.event_name == 'pull_request' && needs.check_approvals.outputs.external_pr == 'false') || (github.event_name == 'pull_request_target' && needs.check_approvals.outputs.external_pr == 'true' && needs.check_approvals.outputs.check_approvals == 'true') }} 37 | runs-on: ubuntu-latest 38 | permissions: 39 | actions: read 40 | contents: read 41 | security-events: write 42 | checks: write 43 | steps: 44 | - name: Checkout 45 | uses: actions/checkout@v6.0.1 46 | 47 | - name: Setup Go 48 | uses: actions/setup-go@v6 49 | with: 50 | go-version-file: go.mod 51 | 52 | - name: Build Project 53 | run: make build 54 | 55 | - name: Black Duck Full Scan 56 | if: ${{ github.event_name != 'pull_request' }} 57 | uses: blackduck-inc/black-duck-security-scan@v2.7.0 58 | with: 59 | blackducksca_url: ${{ secrets.BLACKDUCK_URL }} 60 | blackducksca_token: ${{ secrets.BLACKDUCK_API_TOKEN }} 61 | github_token: ${{ secrets.GITHUB_TOKEN }} 62 | blackducksca_scan_full: true 63 | blackducksca_scan_failure_severities: 'BLOCKER,CRITICAL' 64 | 65 | - name: Black Duck PR Scan 66 | if: ${{ github.event_name == 'pull_request' }} 67 | uses: blackduck-inc/black-duck-security-scan@v2.7.0 68 | env: 69 | DETECT_PROJECT_VERSION_NAME: ${{ github.base_ref }} 70 | with: 71 | blackducksca_url: ${{ secrets.BLACKDUCK_URL }} 72 | blackducksca_token: ${{ secrets.BLACKDUCK_API_TOKEN }} 73 | github_token: ${{ secrets.GITHUB_TOKEN }} 74 | blackducksca_scan_full: false 75 | blackducksca_prComment_enabled: true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Packer Plugin Nutanix 2 | The `Nutanix` multi-component plugin can be used with HashiCorp [Packer](https://www.packer.io) 3 | to create custom images. For the full list of available features for this plugin see [docs](docs). 4 | 5 | --- 6 | 7 | [![Go Report Card](https://goreportcard.com/badge/github.com/nutanix-cloud-native/packer-plugin-nutanix)](https://goreportcard.com/report/github.com/nutanix-cloud-native/packer-plugin-nutanix) 8 | ![CI](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/actions/workflows/integration.yml/badge.svg) 9 | ![Release](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/actions/workflows/release.yml/badge.svg) 10 | 11 | [![release](https://img.shields.io/github/release-pre/nutanix-cloud-native/packer-plugin-nutanix.svg)](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/releases) 12 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/blob/master/LICENSE) 13 | ![Proudly written in Golang](https://img.shields.io/badge/written%20in-Golang-92d1e7.svg) 14 | [![Releases](https://img.shields.io/github/downloads/nutanix-cloud-native/packer-plugin-nutanix/total.svg)](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/releases) 15 | 16 | --- 17 | 18 | ## Installation 19 | 20 | ### Using pre-built releases 21 | 22 | #### Using the `packer init` command 23 | 24 | Starting from version 1.7, Packer supports a new `packer init` command allowing 25 | automatic installation of Packer plugins. Read the 26 | [Packer documentation](https://www.packer.io/docs/commands/init) for more information. 27 | 28 | To install this plugin, copy and paste this code into your Packer configuration . 29 | Then, run [`packer init`](https://www.packer.io/docs/commands/init). 30 | 31 | ```hcl 32 | packer { 33 | required_plugins { 34 | nutanix = { 35 | version = ">= 1.1.4" 36 | source = "github.com/nutanix-cloud-native/nutanix" 37 | } 38 | } 39 | } 40 | ``` 41 | 42 | #### Using the `packer plugin` command 43 | 44 | Just launch `packer plugins install github.com/nutanix-cloud-native/nutanix` 45 | 46 | #### Manual installation 47 | 48 | You can find pre-built binary releases of the plugin [here](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/releases). 49 | Once you have downloaded the latest archive corresponding to your target OS, 50 | uncompress it to retrieve the plugin binary file corresponding to your platform. 51 | To install the plugin, please follow the official Packer documentation on [installing a plugin](https://www.packer.io/docs/extending/plugins/#installing-plugins). 52 | 53 | 54 | #### From Source 55 | 56 | If you prefer to build the plugin from its source code, clone the GitHub repository locally and run the command `make build` from the root directory. 57 | Upon successful compilation, a `packer-plugin-nutanix` plugin binary file can be found in the root directory. 58 | To install the compiled plugin, please follow the official Packer documentation on [installing a plugin](https://www.packer.io/docs/extending/plugins/#installing-plugins). 59 | 60 | ### Configuration 61 | 62 | For more information on how to configure the plugin, please find some examples in the [`example/`](example) directory. 63 | 64 | ## Limitations 65 | ### Building temporary ISOs on MacOS 66 | If you want to use the cd_files Option to create an additional iso-image for kickstart-files or similiar be aware that MacOS won´t create a suitable file. 67 | Please install xorriso for support on MacOS. 68 | ``` 69 | brew install xorriso 70 | ``` 71 | 72 | ## Contributing 73 | See the [contributing docs](CONTRIBUTING.md). 74 | 75 | ## Support 76 | ### Community Plus 77 | 78 | This code is developed in the open with input from the community through issues and PRs. A Nutanix engineering team serves as the maintainer. Documentation is available in the project repository. 79 | 80 | Issues and enhancement requests can be submitted in the [Issues tab of this repository](../../issues). Please search for and review the existing open issues before submitting a new issue. 81 | 82 | ## License 83 | The project is released under version 2.0 of the [Apache license](http://www.apache.org/licenses/LICENSE-2.0). 84 | -------------------------------------------------------------------------------- /example/scripts/win-update.ps1: -------------------------------------------------------------------------------- 1 | # Source : https://github.com/hashicorp/best-practices/blob/master/packer/scripts/windows/install_windows_updates.ps1 2 | # Silence progress bars in PowerShell, which can sometimes feed back strange 3 | # XML data to the Packer output. 4 | $ProgressPreference = "SilentlyContinue" 5 | 6 | Write-Output "Starting PSWindowsUpdate Installation" 7 | ## ACTUAL NOT WORKING SCRIPT 8 | # # Install PSWindowsUpdate for scriptable Windows Updates 9 | # $webDeployURL = "https://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc/file/66095/1/PSWindowsUpdate_1.4.5.zip" 10 | # $filePath = "$($env:TEMP)\PSWindowsUpdate.zip" 11 | 12 | # (New-Object System.Net.WebClient).DownloadFile($webDeployURL, $filePath) 13 | 14 | # # Older versions of Powershell do not have 'Expand Archive' 15 | # # Use Shell.Application custom object to unzip 16 | # # https://stackoverflow.com/questions/27768303/how-to-unzip-a-file-in-powershell 17 | # $shell = New-Object -ComObject Shell.Application 18 | # $zipFile = $shell.NameSpace($filePath) 19 | # $destinationFolder = $shell.NameSpace("C:\Program Files\WindowsPowerShell\Modules") 20 | 21 | # $copyFlags = 0x00 22 | # $copyFlags += 0x04 # Hide progress dialogs 23 | # $copyFlags += 0x10 # Overwrite existing files 24 | 25 | # $destinationFolder.CopyHere($zipFile.Items(), $copyFlags) 26 | # # Clean up 27 | # Remove-Item -Force -Path $filePath 28 | 29 | # Write-Output "Ended PSWindowsUpdate Installation" 30 | 31 | # Write-Output "Starting Windows Update Installation" 32 | 33 | # Try 34 | # { 35 | # Import-Module PSWindowsUpdate -ErrorAction Stop 36 | # } 37 | # Catch 38 | # { 39 | # Write-Error "Unable to install PSWindowsUpdate" 40 | # exit 1 41 | # } 42 | 43 | # if (Test-Path C:\Windows\Temp\PSWindowsUpdate.log) { 44 | # # Save old logs 45 | # Rename-Item -Path C:\Windows\Temp\PSWindowsUpdate.log -NewName PSWindowsUpdate-$((Get-Date).Ticks).log 46 | 47 | # # Uncomment the line below to delete old logs instead 48 | # #Remove-Item -Path C:\Windows\Temp\PSWindowsUpdate.log 49 | # } 50 | 51 | # try { 52 | # $updateCommand = {ipmo PSWindowsUpdate; Get-WUInstall -AcceptAll -IgnoreReboot | Out-File C:\Windows\Temp\PSWindowsUpdate.log} 53 | # $TaskName = "PackerUpdate" 54 | 55 | # $User = [Security.Principal.WindowsIdentity]::GetCurrent() 56 | # $Scheduler = New-Object -ComObject Schedule.Service 57 | 58 | # $Task = $Scheduler.NewTask(0) 59 | 60 | # $RegistrationInfo = $Task.RegistrationInfo 61 | # $RegistrationInfo.Description = $TaskName 62 | # $RegistrationInfo.Author = $User.Name 63 | 64 | # $Settings = $Task.Settings 65 | # $Settings.Enabled = $True 66 | # $Settings.StartWhenAvailable = $True 67 | # $Settings.Hidden = $False 68 | 69 | # $Action = $Task.Actions.Create(0) 70 | # $Action.Path = "powershell" 71 | # $Action.Arguments = "-Command $updateCommand" 72 | 73 | # $Task.Principal.RunLevel = 1 74 | 75 | # $Scheduler.Connect() 76 | # $RootFolder = $Scheduler.GetFolder("\") 77 | # $RootFolder.RegisterTaskDefinition($TaskName, $Task, 6, "SYSTEM", $Null, 1) | Out-Null 78 | # $RootFolder.GetTask($TaskName).Run(0) | Out-Null 79 | 80 | # Write-Output "The Windows Update log will be displayed below this message. No additional output indicates no updates were needed." 81 | # do { 82 | # sleep 1 83 | # if ((Test-Path C:\Windows\Temp\PSWindowsUpdate.log) -and $script:reader -eq $null) { 84 | # $script:stream = New-Object System.IO.FileStream -ArgumentList "C:\Windows\Temp\PSWindowsUpdate.log", "Open", "Read", "ReadWrite" 85 | # $script:reader = New-Object System.IO.StreamReader $stream 86 | # } 87 | # if ($script:reader -ne $null) { 88 | # $line = $Null 89 | # do {$script:reader.ReadLine() 90 | # $line = $script:reader.ReadLine() 91 | # Write-Output $line 92 | # } while ($line -ne $null) 93 | # } 94 | # } while ($Scheduler.GetRunningTasks(0) | Where-Object {$_.Name -eq $TaskName}) 95 | # } finally { 96 | # $RootFolder.DeleteTask($TaskName,0) 97 | # [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Scheduler) | Out-Null 98 | # if ($script:reader -ne $null) { 99 | # $script:reader.Close() 100 | # $script:stream.Dispose() 101 | # } 102 | # } 103 | Write-Output "Ended Windows Update Installation" -------------------------------------------------------------------------------- /.web-docs/scripts/compile-to-webdocs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Converts the folder name that the component documentation file 4 | # is stored in into the integration slug of the component. 5 | componentTypeFromFolderName() { 6 | if [[ "$1" = "builders" ]]; then 7 | echo "builder" 8 | elif [[ "$1" = "provisioners" ]]; then 9 | echo "provisioner" 10 | elif [[ "$1" = "post-processors" ]]; then 11 | echo "post-processor" 12 | elif [[ "$1" = "datasources" ]]; then 13 | echo "data-source" 14 | else 15 | echo "" 16 | fi 17 | } 18 | 19 | # $1: The content to adjust links 20 | # $2: The organization of the integration 21 | rewriteLinks() { 22 | local result="$1" 23 | local organization="$2" 24 | 25 | urlSegment="([^/]+)" 26 | urlAnchor="(#[^/]+)" 27 | 28 | # Rewrite Component Index Page links to the Integration root page. 29 | # 30 | # (\1) (\2) (\3) 31 | # /packer/plugins/datasources/amazon#anchor-tag--> 32 | # /packer/integrations/hashicorp/amazon#anchor-tag 33 | local find="\(\/packer\/plugins\/$urlSegment\/$urlSegment$urlAnchor?\)" 34 | local replace="\(\/packer\/integrations\/$organization\/\2\3\)" 35 | result="$(echo "$result" | sed -E "s/$find/$replace/g")" 36 | 37 | 38 | # Rewrite Component links to the Integration component page 39 | # 40 | # (\1) (\2) (\3) (\4) 41 | # /packer/plugins/datasources/amazon/parameterstore#anchor-tag --> 42 | # /packer/integrations/{organization}/amazon/latest/components/datasources/parameterstore 43 | local find="\(\/packer\/plugins\/$urlSegment\/$urlSegment\/$urlSegment$urlAnchor?\)" 44 | local replace="\(\/packer\/integrations\/$organization\/\2\/latest\/components\/\1\/\3\4\)" 45 | result="$(echo "$result" | sed -E "s/$find/$replace/g")" 46 | 47 | # Rewrite the Component URL segment from the Packer Plugin format 48 | # to the Integrations format 49 | result="$(echo "$result" \ 50 | | sed "s/\/datasources\//\/data-source\//g" \ 51 | | sed "s/\/builders\//\/builder\//g" \ 52 | | sed "s/\/post-processors\//\/post-processor\//g" \ 53 | | sed "s/\/provisioners\//\/provisioner\//g" \ 54 | )" 55 | 56 | echo "$result" 57 | } 58 | 59 | # $1: Docs Dir 60 | # $2: Web Docs Dir 61 | # $3: Component File 62 | # $4: The org of the integration 63 | processComponentFile() { 64 | local docsDir="$1" 65 | local webDocsDir="$2" 66 | local componentFile="$3" 67 | 68 | local escapedDocsDir="$(echo "$docsDir" | sed 's/\//\\\//g' | sed 's/\./\\\./g')" 69 | local componentTypeAndSlug="$(echo "$componentFile" | sed "s/$escapedDocsDir\///g" | sed 's/\.mdx//g')" 70 | 71 | # Parse out the Component Slug & Component Type 72 | local componentSlug="$(echo "$componentTypeAndSlug" | cut -d'/' -f 2)" 73 | local componentType="$(componentTypeFromFolderName "$(echo "$componentTypeAndSlug" | cut -d'/' -f 1)")" 74 | if [[ "$componentType" = "" ]]; then 75 | echo "Failed to process '$componentFile', unexpected folder name." 76 | echo "Documentation for components must be stored in one of:" 77 | echo "builders, provisioners, post-processors, datasources" 78 | exit 1 79 | fi 80 | 81 | 82 | # Calculate the location of where this file will ultimately go 83 | local webDocsFolder="$webDocsDir/components/$componentType/$componentSlug" 84 | mkdir -p "$webDocsFolder" 85 | local webDocsFile="$webDocsFolder/README.md" 86 | local webDocsFileTmp="$webDocsFolder/README.md.tmp" 87 | 88 | # Copy over the file to its webDocsFile location 89 | cp "$componentFile" "$webDocsFile" 90 | 91 | # Remove the Header 92 | local lastMetadataLine="$(grep -n -m 2 '^\-\-\-' "$componentFile" | tail -n1 | cut -d':' -f1)" 93 | cat "$webDocsFile" | tail -n +"$(($lastMetadataLine+2))" > "$webDocsFileTmp" 94 | mv "$webDocsFileTmp" "$webDocsFile" 95 | 96 | # Remove the top H1, as this will be added automatically on the web 97 | cat "$webDocsFile" | tail -n +3 > "$webDocsFileTmp" 98 | mv "$webDocsFileTmp" "$webDocsFile" 99 | 100 | # Rewrite Links 101 | rewriteLinks "$(cat "$webDocsFile")" "$4" > "$webDocsFileTmp" 102 | mv "$webDocsFileTmp" "$webDocsFile" 103 | } 104 | 105 | # Compiles the Packer SDC compiled docs folder down 106 | # to a integrations-compliant folder (web docs) 107 | # 108 | # $1: The directory of the plugin 109 | # $2: The directory of the SDC compiled docs files 110 | # $3: The output directory to place the web-docs files 111 | # $4: The org of the integration 112 | compileWebDocs() { 113 | local docsDir="$1/$2" 114 | local webDocsDir="$1/$3" 115 | 116 | echo "Compiling MDX docs in '$2' to Markdown in '$3'..." 117 | # Create the web-docs directory if it hasn't already been created 118 | mkdir -p "$webDocsDir" 119 | 120 | # Copy the README over 121 | cp "$docsDir/README.md" "$webDocsDir/README.md" 122 | 123 | # Process all MDX component files (exclude index files, which are unsupported) 124 | for file in $(find "$docsDir" | grep "$docsDir/.*/.*\.mdx" | grep --invert-match "index.mdx"); do 125 | processComponentFile "$docsDir" "$webDocsDir" "$file" "$4" 126 | done 127 | } 128 | 129 | compileWebDocs "$1" "$2" "$3" "$4" 130 | -------------------------------------------------------------------------------- /example/source.nutanix.pkr.hcl: -------------------------------------------------------------------------------- 1 | source "nutanix" "centos" { 2 | nutanix_username = var.nutanix_username 3 | nutanix_password = var.nutanix_password 4 | nutanix_endpoint = var.nutanix_endpoint 5 | nutanix_port = var.nutanix_port 6 | nutanix_insecure = var.nutanix_insecure 7 | cluster_name = var.nutanix_cluster 8 | os_type = "Linux" 9 | 10 | vm_disks { 11 | image_type = "DISK_IMAGE" 12 | source_image_name = var.centos_disk_image_name 13 | disk_size_gb = 40 14 | } 15 | 16 | vm_nics { 17 | subnet_name = var.nutanix_subnet 18 | } 19 | 20 | image_categories { 21 | key = "TemplateType" 22 | value = "Vm" 23 | } 24 | 25 | vm_categories { 26 | key = "Environment" 27 | value = "Dev" 28 | } 29 | 30 | vtpm { 31 | enabled = true 32 | } 33 | 34 | image_name = "centos-packer-image" 35 | image_export = false 36 | force_deregister = true 37 | user_data = base64encode(file("scripts/cloud-init/cloud-config-centos.yaml")) 38 | 39 | boot_type = "secure_boot" 40 | 41 | shutdown_command = "echo 'packer' | sudo -S shutdown -P now" 42 | shutdown_timeout = "2m" 43 | ssh_password = "packer" 44 | ssh_username = "centos" 45 | } 46 | 47 | source "nutanix" "ubuntu" { 48 | nutanix_username = var.nutanix_username 49 | nutanix_password = var.nutanix_password 50 | nutanix_endpoint = var.nutanix_endpoint 51 | nutanix_port = var.nutanix_port 52 | nutanix_insecure = var.nutanix_insecure 53 | cluster_name = var.nutanix_cluster 54 | os_type = "Linux" 55 | 56 | vm_disks { 57 | image_type = "DISK_IMAGE" 58 | source_image_name = var.ubuntu_disk_image_name 59 | disk_size_gb = 40 60 | } 61 | 62 | vm_nics { 63 | subnet_name = var.nutanix_subnet 64 | } 65 | 66 | image_name = "ubuntu-packer-image" 67 | force_deregister = true 68 | user_data = base64encode(file("scripts/cloud-init/cloud-config-ubuntu.yaml")) 69 | 70 | shutdown_command = "echo 'packer' | sudo -S shutdown -P now" 71 | shutdown_timeout = "2m" 72 | ssh_password = "packer" 73 | ssh_username = "builder" 74 | } 75 | 76 | source "nutanix" "centos-kickstart" { 77 | nutanix_username = var.nutanix_username 78 | nutanix_password = var.nutanix_password 79 | nutanix_endpoint = var.nutanix_endpoint 80 | nutanix_port = var.nutanix_port 81 | nutanix_insecure = var.nutanix_insecure 82 | cluster_name = var.nutanix_cluster 83 | os_type = "Linux" 84 | 85 | 86 | vm_disks { 87 | image_type = "ISO_IMAGE" 88 | source_image_name = var.centos_iso_image_name 89 | } 90 | 91 | vm_disks { 92 | image_type = "DISK" 93 | disk_size_gb = 40 94 | } 95 | 96 | vm_nics { 97 | subnet_name = var.nutanix_subnet 98 | } 99 | 100 | cd_files = ["scripts/ks.cfg"] 101 | cd_label = "OEMDRV" 102 | 103 | boot_priority = "disk" 104 | 105 | image_name ="centos8-{{isotime `Jan-_2-15:04:05`}}" 106 | shutdown_command = "echo 'packer' | sudo -S shutdown -P now" 107 | shutdown_timeout = "2m" 108 | ssh_password = "packer" 109 | ssh_username = "root" 110 | } 111 | 112 | source "nutanix" "ubuntu-autoinstall" { 113 | nutanix_username = var.nutanix_username 114 | nutanix_password = var.nutanix_password 115 | nutanix_endpoint = var.nutanix_endpoint 116 | nutanix_port = var.nutanix_port 117 | nutanix_insecure = var.nutanix_insecure 118 | cluster_name = var.nutanix_cluster 119 | os_type = "Linux" 120 | 121 | 122 | vm_disks { 123 | image_type = "ISO_IMAGE" 124 | source_image_name = var.ubuntu_iso_image_name 125 | } 126 | 127 | vm_disks { 128 | image_type = "DISK" 129 | disk_size_gb = 40 130 | } 131 | 132 | vm_nics { 133 | subnet_name = var.nutanix_subnet 134 | } 135 | 136 | boot_priority = "disk" 137 | 138 | boot_command = [ 139 | "e", 140 | "", 141 | "", 142 | "autoinstall ds=configdrive ---", 143 | "" 144 | ] 145 | boot_wait = "10s" 146 | user_data = base64encode(file("scripts/cloud-init/autoinstall-ubuntu.yaml")) 147 | 148 | image_name ="ubuntu-{{isotime `Jan-_2-15:04:05`}}" 149 | shutdown_command = "echo 'ubuntu' | sudo -S shutdown -P now" 150 | shutdown_timeout = "2m" 151 | ssh_password = "ubuntu" 152 | ssh_username = "ubuntu" 153 | } 154 | 155 | source "nutanix" "windows" { 156 | nutanix_username = var.nutanix_username 157 | nutanix_password = var.nutanix_password 158 | nutanix_endpoint = var.nutanix_endpoint 159 | nutanix_insecure = var.nutanix_insecure 160 | cluster_name = var.nutanix_cluster 161 | 162 | vm_disks { 163 | image_type = "ISO_IMAGE" 164 | source_image_name = var.windows_2016_iso_image_name 165 | } 166 | 167 | vm_disks { 168 | image_type = "ISO_IMAGE" 169 | source_image_name = var.virtio_iso_image_name 170 | } 171 | 172 | vm_disks { 173 | image_type = "DISK" 174 | disk_size_gb = 40 175 | } 176 | 177 | vm_nics { 178 | subnet_name = var.nutanix_subnet 179 | } 180 | 181 | cd_files = ["scripts/gui/autounattend.xml","scripts/win-update.ps1"] 182 | 183 | boot_priority = "disk" 184 | 185 | image_name ="win-{{isotime `Jan-_2-15:04:05`}}" 186 | shutdown_command = "shutdown /s /t 10 /f /d p:4:1 /c \"Packer Shutdown\"" 187 | shutdown_timeout = "3m" 188 | cpu = 2 189 | os_type = "Windows" 190 | memory_mb = "8192" 191 | communicator = "winrm" 192 | winrm_port = 5986 193 | winrm_insecure = true 194 | winrm_use_ssl = true 195 | winrm_timeout = "45m" 196 | winrm_password = "packer" 197 | winrm_username = "Administrator" 198 | } 199 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/nutanix-cloud-native/packer-plugin-nutanix 2 | 3 | go 1.24.0 4 | 5 | require ( 6 | github.com/google/uuid v1.6.0 7 | github.com/hashicorp/hcl/v2 v2.24.0 8 | github.com/hashicorp/packer-plugin-sdk v0.6.3 9 | github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed 10 | github.com/nutanix-cloud-native/prism-go-client v0.5.5 11 | github.com/zclconf/go-cty v1.16.3 12 | golang.org/x/net v0.44.0 13 | ) 14 | 15 | require ( 16 | cloud.google.com/go v0.110.8 // indirect 17 | cloud.google.com/go/compute/metadata v0.3.0 // indirect 18 | cloud.google.com/go/iam v1.1.3 // indirect 19 | cloud.google.com/go/storage v1.35.1 // indirect 20 | github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect 21 | github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 // indirect 22 | github.com/Microsoft/go-winio v0.6.2 // indirect 23 | github.com/PaesslerAG/gval v1.0.0 // indirect 24 | github.com/PaesslerAG/jsonpath v0.1.1 // indirect 25 | github.com/agext/levenshtein v1.2.3 // indirect 26 | github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect 27 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 28 | github.com/armon/go-metrics v0.4.1 // indirect 29 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect 30 | github.com/aws/aws-sdk-go v1.44.114 // indirect 31 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect 32 | github.com/cenkalti/backoff/v3 v3.2.2 // indirect 33 | github.com/dylanmei/iso8601 v0.1.0 // indirect 34 | github.com/fatih/color v1.16.0 // indirect 35 | github.com/go-jose/go-jose/v4 v4.0.5 // indirect 36 | github.com/go-logr/logr v1.4.1 // indirect 37 | github.com/go-logr/zapr v1.3.0 // indirect 38 | github.com/go-openapi/analysis v0.23.0 // indirect 39 | github.com/go-openapi/errors v0.22.0 // indirect 40 | github.com/go-openapi/jsonpointer v0.21.0 // indirect 41 | github.com/go-openapi/jsonreference v0.21.0 // indirect 42 | github.com/go-openapi/loads v0.22.0 // indirect 43 | github.com/go-openapi/spec v0.21.0 // indirect 44 | github.com/go-openapi/strfmt v0.23.0 // indirect 45 | github.com/go-openapi/swag v0.23.0 // indirect 46 | github.com/go-openapi/validate v0.24.0 // indirect 47 | github.com/gofrs/flock v0.8.1 // indirect 48 | github.com/gofrs/uuid v4.0.0+incompatible // indirect 49 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 50 | github.com/golang/protobuf v1.5.4 // indirect 51 | github.com/google/s2a-go v0.1.7 // indirect 52 | github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect 53 | github.com/googleapis/gax-go/v2 v2.12.0 // indirect 54 | github.com/hashicorp/consul/api v1.25.1 // indirect 55 | github.com/hashicorp/errwrap v1.1.0 // indirect 56 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 57 | github.com/hashicorp/go-getter/gcs/v2 v2.2.2 // indirect 58 | github.com/hashicorp/go-getter/s3/v2 v2.2.2 // indirect 59 | github.com/hashicorp/go-getter/v2 v2.2.2 // indirect 60 | github.com/hashicorp/go-hclog v1.6.3 // indirect 61 | github.com/hashicorp/go-immutable-radix v1.3.1 // indirect 62 | github.com/hashicorp/go-multierror v1.1.1 // indirect 63 | github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 64 | github.com/hashicorp/go-rootcerts v1.0.2 // indirect 65 | github.com/hashicorp/go-safetemp v1.0.0 // indirect 66 | github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect 67 | github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect 68 | github.com/hashicorp/go-sockaddr v1.0.7 // indirect 69 | github.com/hashicorp/go-version v1.6.0 // indirect 70 | github.com/hashicorp/golang-lru v0.5.4 // indirect 71 | github.com/hashicorp/hcl v1.0.0 // indirect 72 | github.com/hashicorp/serf v0.10.1 // indirect 73 | github.com/hashicorp/vault/api v1.14.0 // indirect 74 | github.com/hashicorp/yamux v0.1.1 // indirect 75 | github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect 76 | github.com/jmespath/go-jmespath v0.4.0 // indirect 77 | github.com/josharian/intern v1.0.0 // indirect 78 | github.com/klauspost/compress v1.13.6 // indirect 79 | github.com/kr/fs v0.1.0 // indirect 80 | github.com/mailru/easyjson v0.7.7 // indirect 81 | github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect 82 | github.com/masterzen/winrm v0.0.0-20210623064412-3b76017826b0 // indirect 83 | github.com/mattn/go-colorable v0.1.13 // indirect 84 | github.com/mattn/go-isatty v0.0.20 // indirect 85 | github.com/mitchellh/go-fs v0.0.0-20180402235330-b7b9ca407fff // indirect 86 | github.com/mitchellh/go-homedir v1.1.0 // indirect 87 | github.com/mitchellh/go-testing-interface v1.14.1 // indirect 88 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 89 | github.com/mitchellh/iochan v1.0.0 // indirect 90 | github.com/mitchellh/mapstructure v1.5.0 // indirect 91 | github.com/mitchellh/reflectwalk v1.0.2 // indirect 92 | github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect 93 | github.com/oklog/ulid v1.3.1 // indirect 94 | github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db // indirect 95 | github.com/pkg/sftp v1.13.2 // indirect 96 | github.com/ryanuber/go-glob v1.0.0 // indirect 97 | github.com/ugorji/go/codec v1.2.6 // indirect 98 | github.com/ulikunitz/xz v0.5.10 // indirect 99 | github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect 100 | github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect 101 | go.mongodb.org/mongo-driver v1.14.0 // indirect 102 | go.opencensus.io v0.24.0 // indirect 103 | go.uber.org/multierr v1.10.0 // indirect 104 | go.uber.org/zap v1.27.0 // indirect 105 | golang.org/x/crypto v0.42.0 // indirect 106 | golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect 107 | golang.org/x/mobile v0.0.0-20210901025245-1fde1d6c3ca1 // indirect 108 | golang.org/x/mod v0.27.0 // indirect 109 | golang.org/x/oauth2 v0.30.0 // indirect 110 | golang.org/x/sync v0.17.0 // indirect 111 | golang.org/x/sys v0.36.0 // indirect 112 | golang.org/x/term v0.35.0 // indirect 113 | golang.org/x/text v0.29.0 // indirect 114 | golang.org/x/time v0.11.0 // indirect 115 | golang.org/x/tools v0.36.0 // indirect 116 | golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect 117 | google.golang.org/api v0.150.0 // indirect 118 | google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect 119 | google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect 120 | google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect 121 | google.golang.org/grpc v1.59.0 // indirect 122 | google.golang.org/protobuf v1.33.0 // indirect 123 | gopkg.in/yaml.v3 v3.0.1 // indirect 124 | ) 125 | 126 | replace ( 127 | github.com/hashicorp/consul => github.com/hashicorp/consul v1.10.4 128 | github.com/hashicorp/vault => github.com/hashicorp/vault v1.4.2 129 | ) 130 | 131 | replace github.com/zclconf/go-cty => github.com/nywilken/go-cty v1.13.3 // added by packer-sdc fix as noted in github.com/hashicorp/packer-plugin-sdk/issues/187 132 | -------------------------------------------------------------------------------- /example/windows/files/autounattend.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 24 | 25 | 26 | 27 | 28 | 29 | 1 30 | 500 31 | Primary 32 | 33 | 34 | 2 35 | 100 36 | EFI 37 | 38 | 39 | 3 40 | 128 41 | MSR 42 | 43 | 44 | 4 45 | true 46 | Primary 47 | 48 | 49 | 50 | 51 | 1 52 | 1 53 | 54 | NTFS 55 | de94bba4-06d1-4d40-a16a-bfd50179d6ac 56 | 57 | 58 | 2 59 | 2 60 | 61 | FAT32 62 | 63 | 64 | 3 65 | 3 66 | 67 | 68 | 4 69 | 4 70 | NTFS 71 | 72 | 73 | 0 74 | true 75 | 76 | OnError 77 | 78 | 79 | true 80 | 81 | 82 | 83 | Never 84 | 85 | 86 | 87 | 88 | 89 | 0 90 | 4 91 | 92 | OnError 93 | false 94 | 95 | 96 | 100 | 101 | /IMAGE/NAME 102 | Windows 11 Enterprise 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | e:\Windows 11\x64 113 | 114 | 115 | 116 | 117 | 118 | en-US 119 | 120 | en-US 121 | en-US 122 | en-US 123 | en-US 124 | 125 | 126 | 127 | 128 | true 129 | 130 | 131 | false 132 | false 133 | 134 | 135 | true 136 | 137 | 138 | true 139 | 140 | 141 | 142 | 143 | 1 144 | Set Execution Policy 64 Bit 145 | cmd.exe /c powershell.exe -Command "Set-ExecutionPolicy -ExecutionPolicy Bypass -Force" 146 | 147 | 148 | 2 149 | Set Execution Policy 32 Bit 150 | cmd.exe /c powershell.exe -Command "Set-ExecutionPolicy -ExecutionPolicy Bypass -Force" 151 | 152 | 153 | 3 154 | Enable the Admin Account 155 | cmd /c net user Administrator /active:yes 156 | 157 | 158 | 4 159 | Create Setup Folder for SetupComplete.cmd 160 | cmd /c mkdir C:\Windows\Setup\Scripts 161 | 162 | 163 | 5 164 | Copy SetupComplete.cmd 165 | cmd /c copy f:\setupcomplete.cmd C:\Windows\Setup\Scripts\setupcomplete.cmd 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | Nutanix.123!! 175 | true</PlainText> 176 | </AdministratorPassword> 177 | </UserAccounts> 178 | <OOBE> 179 | <HideEULAPage>true</HideEULAPage> 180 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 181 | <SkipMachineOOBE>true</SkipMachineOOBE> 182 | <SkipUserOOBE>true</SkipUserOOBE> 183 | </OOBE> 184 | <TimeZone>Pacific Standard Time</TimeZone> 185 | <RegisteredOrganization>Nutanix</RegisteredOrganization> 186 | <RegisteredOwner>Nutanix</RegisteredOwner> 187 | <ComputerName>*</ComputerName> 188 | </component> 189 | </settings> 190 | 191 | <cpi:offlineImage cpi:source="" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> 192 | </unattend> 193 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /docs/builders/nutanix.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | description: > 3 | The Nutanix packer plugin allow to use Packer on Nutanix AHV platform. 4 | page_title: Nutanix plugin 5 | nav_title: Nutanix 6 | --- 7 | 8 | # Nutanix Builder 9 | 10 | This document is going to detail all Nutanix plugin parameters. 11 | 12 | ## Principle 13 | The Nutanix plugin will create a temporary VM as foundation of your Packer image, apply all providers you define to customize your image, then clone the VM disk image as your final Packer image. 14 | 15 | ## Environment configuration 16 | These parameters allow to define information about platform and temporary VM used to create the image. 17 | 18 | ### Required 19 | - `nutanix_username` (string) - User used for Prism Central login. 20 | - `nutanix_password` (string) - Password of this user for Prism Central login. 21 | - `nutanix_endpoint` (string) - Prism Central FQDN or IP. 22 | - `cluster_name` or `cluster_uuid` (string) - Nutanix cluster name or uuid used to create and store image. 23 | - `os_type` (string) - OS Type ("Linux" or "Windows"). 24 | 25 | Starting `v1.1.4` the Nutanix Packer Plugin supports Prism Central Service Accounts. To use a Service Account, you need to provide `X-ntnx-api-key` as the `nutanix_username` and the corresponding API Key as the `nutanix_password`. 26 | 27 | ### Optional 28 | - `nutanix_port` (number) - Port used for connection to Prism Central. 29 | - `nutanix_insecure` (bool) - Authorize connection to Prism Central without valid certificate. 30 | - `vm_name` (string) - Name of the temporary VM to create. If not specified a random `packer-*` name will be used. 31 | - `cpu` (number) - Number of vCPU for temporary VM (default is 1). 32 | - `core` (number) - Number of cores per vCPU for temporary VM (default is 1). 33 | - `memory_mb` (number) - Size of vRAM for temporary VM (in megabytes). 34 | - `hardware_virtualization` (bool) - Enable hardware virtualization for temporary VM (default is false). 35 | - `cd_files` (array of strings) - A list of files to place onto a CD that is attached when the VM is booted. This can include either files or directories; any directories will be copied onto the CD recursively, preserving directory structure hierarchy. 36 | - `cd_label` (string) - Label of this CD Drive. 37 | - `boot_type` (string) - Type of boot used on the temporary VM ("legacy", "uefi" or "secure_boot", default is "legacy"). 38 | - `boot_priority` (string) - Priority of boot device ("cdrom" or "disk", default is "cdrom". UEFI support need AHV 8.0.12+, 9.1.1.2+, 9.1.3+, 9.2+ or 10.0+). 39 | - `vm_categories` ([]Category) - Assign Categories to the vm. 40 | - `project` (string) - Assign Project to the vm. 41 | - `gpu` ([] GPU) - GPU in cluster name to be attached on temporary VM. 42 | - `serialport` (bool) - Add a serial port to the temporary VM. This is required for some Linux Cloud Images that will have a kernel panic if a serial port is not present on first boot. 43 | 44 | #### vTPM 45 | 46 | Use `vtpm{}` entry to configure vTPM on the temporary VM. 47 | 48 | 49 | All parameters of this `vtpm` section are described below. 50 | 51 | - `enabled` (bool) - Enable vTPM for the temporary VM (default is false). 52 | 53 | 54 | Sample: 55 | ```hcl 56 | vtpm { 57 | enabled = true 58 | } 59 | ``` 60 | 61 | ## Output configuration 62 | These parameters allow to configure everything around image creation, from the temporary VM connection to the final image definition. 63 | 64 | ### All OS 65 | - `image_name` (string) - Name of the output image. 66 | - `image_description` (string) - Description for output image. 67 | - `image_categories` ([]Category) - Assign Categories to the image. 68 | - `force_deregister` (bool) - Allow output image override if already exists. 69 | - `image_delete` (bool) - Delete image once build process is completed (default is false). 70 | - `image_skip` (bool) - Skip image creation (default is false). 71 | - `image_export` (bool) - Export raw image in the current folder (default is false). 72 | - `fail_if_image_exists` (bool) - Fail the build if an image with the same name already exists (default is false). 73 | - `shutdown_command` (string) - Command line to shutdown your temporary VM. 74 | - `shutdown_timeout` (string) - Timeout for VM shutdown (format : 2m). 75 | - `vm_force_delete` (bool) - Delete vm even if build is not succesful (default is false). 76 | - `vm_retain` (bool) - Retain the temporary VM after build process is completed (default is false). 77 | - `disable_stop_instance` (bool) - When `true`, prevents Packer from automatically stopping the build instance after provisioning completes. Your final provisioner must handle stopping the instance, or the build will timeout (default is false). 78 | 79 | ### Dedicated to Linux 80 | - `user_data` (string) - cloud-init content base64 encoded. 81 | - `ssh_username` (string) - user for ssh connection initiated by Packer. 82 | - `ssh_password` (string) - password for the ssh user. 83 | 84 | ### Dedicated to Windows 85 | - `winrm_port` (number) - Port for WinRM communication (default is 5986). 86 | - `winrm_insecure` (bool) - Allow insecure connection to WinRM. 87 | - `winrm_use_ssl` (bool) - Request SSL connection with WinRM. 88 | - `winrm_timeout` (string) - Timeout for WinRM (format 45m). 89 | - `winrm_username` (string) - User login for WinRM connection. 90 | - `winrm_password` (string) - Password this User. 91 | 92 | ## Disk configuration 93 | Use `vm_disks{}` entry to configure disk to your VM image. If you want to configure several disks, use this entry multiple times. 94 | 95 | All parameters of this `vm_disks` section are described below. 96 | 97 | 3 types of disk configurations can be used: 98 | - disk (create an empty disk) 99 | - disk image (create disk from Nutanix image library) 100 | - ISO image (create disk from ISO image) 101 | 102 | ### Disk 103 | - `image_type` (string) - "DISK". 104 | - `disk_size_gb` (number) - size of th disk (in gigabytes). 105 | - `storage_container_uuid` (string) - UUID of the storage container where the disk image will be created. If not specified, the default storage container for the cluster will be used. 106 | 107 | 108 | Sample: 109 | ```hcl 110 | vm_disks { 111 | image_type = "DISK" 112 | disk_size_gb = 30 113 | } 114 | ``` 115 | 116 | ### Disk image 117 | - `image_type` (string) - "DISK_IMAGE" (you must use one of the three following parameters to source the image). 118 | - `source_image_name` (string) - Name of the image used as disk source. 119 | - `source_image_uuid` (string) - UUID of the image used as disk source. 120 | - `source_image_uri` (string) - URI of the image used as disk source (if image is not already on the cluster, it will download and store it before launching output image creation process). 121 | - `source_image_path` (string) - Path to the local image used as disk source (it will upload it before launching output image creation process). 122 | - `source_image_checksum` (string) - Checksum of the image used as disk source (work only with `source_image_uri` and if image is not already present in the library). 123 | - `source_image_checksum_type` (string) - Type of checksum used for `source_image_checksum` (`sha256` or `sha1` ). 124 | - `source_image_delete` (bool) - Delete image once build process is completed (default is false). 125 | - `source_image_force` (bool) - Always download and replace image even if already exist (default is false). 126 | - `disk_size_gb` (number) - size of the disk (in gigabytes). 127 | 128 | Sample: 129 | ```hcl 130 | vm_disks { 131 | image_type = "DISK_IMAGE" 132 | source_image_name = "<myDiskImage>" 133 | disk_size_gb = 40 134 | } 135 | ``` 136 | ### ISO Image 137 | - `image_type` (string) - "ISO_IMAGE". 138 | - `source_image_name` (string) - Name of the ISO image to mount. 139 | - `source_image_uuid` (string) - UUID of the ISO image to mount. 140 | - `source_image_uri` (string) - URI of the image used as ISO source (if image is not already on the cluster, it will download and store it before launching output image creation process). 141 | - `source_image_path` (string) - Path to the local image used as ISO source (it will upload it before launching output image creation process). 142 | - `source_image_checksum` (string) - Checksum of the image used as ISO source (work only with `source_image_uri` and if image is not already present in the library). 143 | - `source_image_checksum_type` (string) - Type of checksum used for `source_image_checksum` (`sha256` or `sha1` ). 144 | - `source_image_delete` (bool) - Delete source image once build process is completed (default is false). 145 | - `source_image_force` (bool) - Always download and replace source image even if already exist (default is false). 146 | 147 | Sample: 148 | ```hcl 149 | vm_disks { 150 | image_type = "ISO_IMAGE" 151 | source_image_name = "<myISOimage>" 152 | } 153 | ``` 154 | 155 | ## VM Clean 156 | 157 | Use `vm_clean{}` entry to configure VM cleaning options. This section allows you to clean up the temporary VM after the image creation process is completed. 158 | It can be useful to remove unnecessary components or reset the VM to a clean state before creating a template or exporting an OVA. 159 | 160 | All parameters of this `vm_clean` section are described below. 161 | 162 | - `cdrom` (bool) - Remove all CD-ROMs from the VM (default is false). 163 | 164 | Sample: 165 | ```hcl 166 | vm_clean { 167 | cdrom = true 168 | } 169 | ``` 170 | 171 | ## Template configuration 172 | 173 | Use `template{}` entry to create a template from the temporary VM. 174 | 175 | Template feature need Prism Central 2024.3+ or later. 176 | 177 | All parameters of this `template` section are described below. 178 | 179 | - `create` (bool) - Create a template from the temporary VM (default is false). 180 | - `name` (string) - Name of the template to create (default is the vm_name). 181 | - `description` (string) - Description of the template to create (default is no description). 182 | 183 | Sample: 184 | ```hcl 185 | template { 186 | create = true 187 | name = "myTemplate" 188 | description = "This is my template" 189 | } 190 | ``` 191 | 192 | ## OVA Config 193 | Use `ova{}` entry to configure the OVA creation & export 194 | 195 | All parameters of this `ova` section are described below. 196 | 197 | - `create` (bool) - Create OVA image for the vm (default is false). 198 | - `export` (bool) - Export OVA image in the current folder (default is false). 199 | - `format` (string) - Format of the ova image (allowed values: 'vmdk', 'qcow2', default 'vmdk'). 200 | - `name` (string) - Name of the the OVA image (default is the vm_name). 201 | 202 | Sample: 203 | ```hcl 204 | ova { 205 | create = true 206 | export = true 207 | format = "vmdk" 208 | name = "myExportedOVA" 209 | } 210 | ``` 211 | 212 | ## Network Configuration 213 | Use `vm_nics{}` entry to configure NICs in your image 214 | 215 | In this section, you have to define network you will to connect with one of this keyword : 216 | 217 | - `subnet_name` (string) - Name of the cluster subnet to use. 218 | - `subnet_uuid` (string) - UUID of the cluster subnet to use. 219 | - `mac_address` (string) - The network card MAC address. If not specified, a random MAC address will be generated. 220 | 221 | Sample 222 | ```hcl 223 | vm_nics { 224 | subnet_name = "<mySubnet>" 225 | } 226 | ``` 227 | 228 | ### Categories Configuration 229 | 230 | Use `image_categories{}` and `vm_categories{}` to assign category to your image or vm. If you want to assign multiple categories , use the entry multiple times. 231 | 232 | In this section, you have to define category you will to assign with the following parameters: 233 | 234 | - `key` (string) - Name of the category to assign. 235 | - `value` (string) - Value of the category to assign. 236 | 237 | Sample 238 | ```hcl 239 | image_categories { 240 | key = "OSType" 241 | value = "ubuntu-22.04" 242 | } 243 | ``` 244 | 245 | Note: Categories must already be present in Prism Central. 246 | 247 | ## GPU Configuration 248 | 249 | Use `GPU` to assign a GPU that is present on `cluster-name` on the temporary vm. Add the name of the GPU you wish to attach. 250 | 251 | Sample 252 | 253 | ```hcl 254 | gpu { 255 | name = "Ampere 40" 256 | } 257 | ``` 258 | 259 | ## Boot Configuration 260 | 261 | @include 'packer-plugin-sdk/bootcommand/BootConfig.mdx' 262 | 263 | @include 'packer-plugin-sdk/bootcommand/VNCConfig.mdx' 264 | 265 | **Optional**: 266 | 267 | @include 'packer-plugin-sdk/bootcommand/BootConfig-not-required.mdx' 268 | 269 | @include 'packer-plugin-sdk/bootcommand/VNCConfig-not-required.mdx' 270 | 271 | ## IP Wait configuration 272 | 273 | **Optional**: 274 | 275 | @include 'builder/nutanix/WaitIpConfig-not-required.mdx' 276 | 277 | ## Communicator Configuration 278 | 279 | **Optional**: 280 | 281 | ##### Common 282 | 283 | @include 'packer-plugin-sdk/communicator/Config-not-required.mdx' 284 | 285 | ##### SSH 286 | 287 | @include 'packer-plugin-sdk/communicator/SSH-not-required.mdx' 288 | 289 | @include 'packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx' 290 | 291 | ##### Windows Remote Management (WinRM) 292 | 293 | @include 'packer-plugin-sdk/communicator/WinRM-not-required.mdx' 294 | 295 | ## Samples 296 | 297 | You can find samples [here](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/tree/main/example) for these instructions usage. 298 | -------------------------------------------------------------------------------- /example/scripts/gui/autounattend.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <unattend xmlns="urn:schemas-microsoft-com:unattend"> 3 | <settings pass="windowsPE"> 4 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 5 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-international-core-winpe --> 6 | <SetupUILanguage> 7 | <UILanguage>en-US</UILanguage> 8 | </SetupUILanguage> 9 | <InputLocale>en-US</InputLocale> 10 | <SystemLocale>en-US</SystemLocale> 11 | <UILanguage>en-US</UILanguage> 12 | <UILanguageFallback>en-US</UILanguageFallback> 13 | <UserLocale>en-US</UserLocale> 14 | </component> 15 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 16 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-setup --> 17 | <DiskConfiguration> 18 | <Disk wcm:action="add"> 19 | <CreatePartitions> 20 | <CreatePartition wcm:action="add"> 21 | <Type>Primary</Type> 22 | <Order>1</Order> 23 | <Size>499</Size> 24 | </CreatePartition> 25 | <CreatePartition wcm:action="add"> 26 | <Order>2</Order> 27 | <Type>Primary</Type> 28 | <Extend>true</Extend> 29 | </CreatePartition> 30 | </CreatePartitions> 31 | <ModifyPartitions> 32 | <ModifyPartition wcm:action="add"> 33 | <Active>true</Active> 34 | <Format>NTFS</Format> 35 | <Label>boot</Label> 36 | <Order>1</Order> 37 | <PartitionID>1</PartitionID> 38 | </ModifyPartition> 39 | <ModifyPartition wcm:action="add"> 40 | <Format>NTFS</Format> 41 | <Label>Windows 2016</Label> 42 | <Letter>C</Letter> 43 | <Order>2</Order> 44 | <PartitionID>2</PartitionID> 45 | </ModifyPartition> 46 | </ModifyPartitions> 47 | <DiskID>0</DiskID> 48 | <WillWipeDisk>true</WillWipeDisk> 49 | </Disk> 50 | </DiskConfiguration> 51 | <ImageInstall> 52 | <OSImage> 53 | <InstallFrom> 54 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-setup-imageinstall-dataimage-installfrom-metadata-key --> 55 | <!-- Get-WindowsImage -ImagePath D:\sources\install.wim --> 56 | <MetaData wcm:action="add"> 57 | <Key>/IMAGE/INDEX</Key> 58 | <Value>2</Value> 59 | </MetaData> 60 | </InstallFrom> 61 | <InstallTo> 62 | <DiskID>0</DiskID> 63 | <PartitionID>2</PartitionID> 64 | </InstallTo> 65 | </OSImage> 66 | </ImageInstall> 67 | <UserData> 68 | <!-- Product Key from http://technet.microsoft.com/en-us/library/jj612867.aspx --> 69 | <ProductKey> 70 | <!-- Do not uncomment the Key element if you are using trial ISOs --> 71 | <!-- You must uncomment the Key element (and optionally insert your own key) if you are using retail or volume license ISOs --> 72 | <!--<Key>WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY</Key>--> 73 | <WillShowUI>OnError</WillShowUI> 74 | </ProductKey> 75 | <AcceptEula>true</AcceptEula> 76 | <FullName>Packer</FullName> 77 | <Organization>Packer</Organization> 78 | </UserData> 79 | </component> 80 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 81 | <DriverPaths> 82 | <PathAndCredentials wcm:action="add" wcm:keyValue="1"> 83 | <Path>e:\Windows Server 2016\amd64</Path> 84 | </PathAndCredentials> 85 | </DriverPaths> 86 | </component> 87 | </settings> 88 | <settings pass="specialize"> 89 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 90 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-international-core --> 91 | <InputLocale>de-DE</InputLocale> 92 | <SystemLocale>en-US</SystemLocale> 93 | <UILanguage>en-US</UILanguage> 94 | <UILanguageFallback>en-US</UILanguageFallback> 95 | <UserLocale>de-DE</UserLocale> 96 | </component> 97 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 98 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-shell-setup --> 99 | <ComputerName>packer-win2016</ComputerName> 100 | <TimeZone>Romance Standard Time</TimeZone> 101 | </component> 102 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 103 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-servermanager-svrmgrnc --> 104 | <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon> 105 | </component> 106 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 107 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-ie-esc --> 108 | <IEHardenAdmin>false</IEHardenAdmin> 109 | <IEHardenUser>true</IEHardenUser> 110 | </component> 111 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-OutOfBoxExperience" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 112 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-outofboxexperience --> 113 | <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon> 114 | </component> 115 | <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"> 116 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-security-spp-ux --> 117 | <SkipAutoActivation>true</SkipAutoActivation> 118 | </component> 119 | </settings> 120 | <settings pass="oobeSystem"> 121 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 122 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-shell-setup --> 123 | <AutoLogon> 124 | <Password> 125 | <Value>packer</Value> 126 | <PlainText>true</PlainText> 127 | </Password> 128 | <Enabled>true</Enabled> 129 | <Username>Administrator</Username> 130 | </AutoLogon> 131 | <FirstLogonCommands> 132 | <SynchronousCommand wcm:action="add"> 133 | <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "WinRMCertificate"</CommandLine> 134 | <Description>Certificate for WinRM</Description> 135 | <Order>1</Order> 136 | <RequiresUserInput>true</RequiresUserInput> 137 | </SynchronousCommand> 138 | <SynchronousCommand wcm:action="add"> 139 | <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command Enable-PSRemoting -SkipNetworkProfileCheck -Force</CommandLine> 140 | <Description>Enable WinRM</Description> 141 | <Order>2</Order> 142 | <RequiresUserInput>true</RequiresUserInput> 143 | </SynchronousCommand> 144 | <SynchronousCommand wcm:action="add"> 145 | <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command ($cert = gci Cert:\LocalMachine\My\) -and (New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $cert.Thumbprint –Force)</CommandLine> 146 | <Description>Add HTTPS WinRM listener with previously generated certificate</Description> 147 | <Order>3</Order> 148 | <RequiresUserInput>true</RequiresUserInput> 149 | </SynchronousCommand> 150 | <SynchronousCommand wcm:action="add"> 151 | <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command New-NetFirewallRule -DisplayName 'Windows Remote Management (HTTPS-In)' -Name 'Windows Remote Management (HTTPS-In)' -Profile Any -LocalPort 5986 -Protocol TCP</CommandLine> 152 | <Description>Add firewall exception to TCP port 5986 for WinRM over HTTPS</Description> 153 | <Order>4</Order> 154 | <RequiresUserInput>true</RequiresUserInput> 155 | </SynchronousCommand> 156 | <SynchronousCommand wcm:action="add"> 157 | <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command Set-Item WSMan:\localhost\Service\Auth\Basic -Value $true</CommandLine> 158 | <Description>Enable Basic authentication</Description> 159 | <Order>5</Order> 160 | <RequiresUserInput>true</RequiresUserInput> 161 | </SynchronousCommand> 162 | <SynchronousCommand wcm:action="add"> 163 | <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command Stop-Service WinRM</CommandLine> 164 | <Description>Stop the WinRM service to allow the dism process to finish before packer executes scripts</Description> 165 | <Order>6</Order> 166 | <RequiresUserInput>true</RequiresUserInput> 167 | </SynchronousCommand> 168 | <SynchronousCommand wcm:action="add"> 169 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> 170 | <Order>7</Order> 171 | <Description>Show file extensions in Explorer</Description> 172 | </SynchronousCommand> 173 | <SynchronousCommand wcm:action="add"> 174 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> 175 | <Order>8</Order> 176 | <Description>Zero Hibernation File</Description> 177 | </SynchronousCommand> 178 | <SynchronousCommand wcm:action="add"> 179 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> 180 | <Order>9</Order> 181 | <Description>Disable Hibernation Mode</Description> 182 | </SynchronousCommand> 183 | <SynchronousCommand wcm:action="add"> 184 | <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command dism /online /quiet /set-edition:ServerDatacenter /productkey:CB7KF-BWN84-R7R2Y-793K2-8XDDG /accepteula</CommandLine> 185 | <Order>10</Order> 186 | <Description>Switch from EVAL to VL</Description> 187 | </SynchronousCommand> 188 | </FirstLogonCommands> 189 | <OOBE> 190 | <HideEULAPage>true</HideEULAPage> 191 | <HideLocalAccountScreen>true</HideLocalAccountScreen> 192 | <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> 193 | <HideOnlineAccountScreens>true</HideOnlineAccountScreens> 194 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 195 | <NetworkLocation>Home</NetworkLocation> 196 | <ProtectYourPC>1</ProtectYourPC> 197 | </OOBE> 198 | <UserAccounts> 199 | <AdministratorPassword> 200 | <Value>packer</Value> 201 | <PlainText>true</PlainText> 202 | </AdministratorPassword> 203 | </UserAccounts> 204 | <RegisteredOwner /> 205 | </component> 206 | </settings> 207 | <settings pass="offlineServicing"> 208 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 209 | <!-- https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-lua-settings --> 210 | <EnableLUA>false</EnableLUA> 211 | </component> 212 | </settings> 213 | <cpi:offlineImage xmlns:cpi="urn:schemas-microsoft-com:cpi" cpi:source="" /> 214 | </unattend> -------------------------------------------------------------------------------- /example/windows/files/scripts/ConfigureRemotingForAnsible.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 3.0 2 | 3 | # Configure a Windows host for remote management with Ansible 4 | # ----------------------------------------------------------- 5 | # 6 | # This script checks the current WinRM (PS Remoting) configuration and makes 7 | # the necessary changes to allow Ansible to connect, authenticate and 8 | # execute PowerShell commands. 9 | # 10 | # IMPORTANT: This script uses self-signed certificates and authentication mechanisms 11 | # that are intended for development environments and evaluation purposes only. 12 | # Production environments and deployments that are exposed on the network should 13 | # use CA-signed certificates and secure authentication mechanisms such as Kerberos. 14 | # 15 | # To run this script in Powershell: 16 | # 17 | # [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 18 | # $url = "https://raw.githubusercontent.com/ansible/ansible-documentation/devel/examples/scripts/ConfigureRemotingForAnsible.ps1" 19 | # $file = "$env:temp\ConfigureRemotingForAnsible.ps1" 20 | # 21 | # (New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file) 22 | # 23 | # powershell.exe -ExecutionPolicy ByPass -File $file 24 | # 25 | # All events are logged to the Windows EventLog, useful for unattended runs. 26 | # 27 | # Use option -Verbose in order to see the verbose output messages. 28 | # 29 | # Use option -CertValidityDays to specify how long this certificate is valid 30 | # starting from today. So you would specify -CertValidityDays 3650 to get 31 | # a 10-year valid certificate. 32 | # 33 | # Use option -ForceNewSSLCert if the system has been SysPreped and a new 34 | # SSL Certificate must be forced on the WinRM Listener when re-running this 35 | # script. This is necessary when a new SID and CN name is created. 36 | # 37 | # Use option -EnableCredSSP to enable CredSSP as an authentication option. 38 | # 39 | # Use option -DisableBasicAuth to disable basic authentication. 40 | # 41 | # Use option -SkipNetworkProfileCheck to skip the network profile check. 42 | # Without specifying this the script will only run if the device's interfaces 43 | # are in DOMAIN or PRIVATE zones. Provide this switch if you want to enable 44 | # WinRM on a device with an interface in PUBLIC zone. 45 | # 46 | # Use option -SubjectName to specify the CN name of the certificate. This 47 | # defaults to the system's hostname and generally should not be specified. 48 | 49 | # Written by Trond Hindenes <trond@hindenes.com> 50 | # Updated by Chris Church <cchurch@ansible.com> 51 | # Updated by Michael Crilly <mike@autologic.cm> 52 | # Updated by Anton Ouzounov <Anton.Ouzounov@careerbuilder.com> 53 | # Updated by Nicolas Simond <contact@nicolas-simond.com> 54 | # Updated by Dag Wieërs <dag@wieers.com> 55 | # Updated by Jordan Borean <jborean93@gmail.com> 56 | # Updated by Erwan Quélin <erwan.quelin@gmail.com> 57 | # Updated by David Norman <david@dkn.email> 58 | # 59 | # Version 1.0 - 2014-07-06 60 | # Version 1.1 - 2014-11-11 61 | # Version 1.2 - 2015-05-15 62 | # Version 1.3 - 2016-04-04 63 | # Version 1.4 - 2017-01-05 64 | # Version 1.5 - 2017-02-09 65 | # Version 1.6 - 2017-04-18 66 | # Version 1.7 - 2017-11-23 67 | # Version 1.8 - 2018-02-23 68 | # Version 1.9 - 2018-09-21 69 | 70 | # Support -Verbose option 71 | [CmdletBinding()] 72 | 73 | Param ( 74 | [string]$SubjectName = $env:COMPUTERNAME, 75 | [int]$CertValidityDays = 1095, 76 | [switch]$SkipNetworkProfileCheck, 77 | $CreateSelfSignedCert = $true, 78 | [switch]$ForceNewSSLCert, 79 | [switch]$GlobalHttpFirewallAccess, 80 | [switch]$DisableBasicAuth = $false, 81 | [switch]$EnableCredSSP 82 | ) 83 | 84 | Function Write-ProgressLog { 85 | $Message = $args[0] 86 | Write-EventLog -LogName Application -Source $EventSource -EntryType Information -EventId 1 -Message $Message 87 | } 88 | 89 | Function Write-VerboseLog { 90 | $Message = $args[0] 91 | Write-Verbose $Message 92 | Write-ProgressLog $Message 93 | } 94 | 95 | Function Write-HostLog { 96 | $Message = $args[0] 97 | Write-Output $Message 98 | Write-ProgressLog $Message 99 | } 100 | 101 | Function New-LegacySelfSignedCert { 102 | Param ( 103 | [string]$SubjectName, 104 | [int]$ValidDays = 1095 105 | ) 106 | 107 | $hostnonFQDN = $env:computerName 108 | $hostFQDN = [System.Net.Dns]::GetHostByName(($env:computerName)).Hostname 109 | $SignatureAlgorithm = "SHA256" 110 | 111 | $name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1" 112 | $name.Encode("CN=$SubjectName", 0) 113 | 114 | $key = New-Object -COM "X509Enrollment.CX509PrivateKey.1" 115 | $key.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider" 116 | $key.KeySpec = 1 117 | $key.Length = 4096 118 | $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)" 119 | $key.MachineContext = 1 120 | $key.Create() 121 | 122 | $serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1" 123 | $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") 124 | $ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1" 125 | $ekuoids.Add($serverauthoid) 126 | $ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" 127 | $ekuext.InitializeEncode($ekuoids) 128 | 129 | $cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1" 130 | $cert.InitializeFromPrivateKey(2, $key, "") 131 | $cert.Subject = $name 132 | $cert.Issuer = $cert.Subject 133 | $cert.NotBefore = (Get-Date).AddDays(-1) 134 | $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays) 135 | 136 | $SigOID = New-Object -ComObject X509Enrollment.CObjectId 137 | $SigOID.InitializeFromValue(([Security.Cryptography.Oid]$SignatureAlgorithm).Value) 138 | 139 | [string[]] $AlternativeName += $hostnonFQDN 140 | $AlternativeName += $hostFQDN 141 | $IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames 142 | 143 | foreach ($AN in $AlternativeName) { 144 | $AltName = New-Object -ComObject X509Enrollment.CAlternativeName 145 | $AltName.InitializeFromString(0x3, $AN) 146 | $IAlternativeNames.Add($AltName) 147 | } 148 | 149 | $SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames 150 | $SubjectAlternativeName.InitializeEncode($IAlternativeNames) 151 | 152 | [String[]]$KeyUsage = ("DigitalSignature", "KeyEncipherment") 153 | $KeyUsageObj = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage 154 | $KeyUsageObj.InitializeEncode([int][Security.Cryptography.X509Certificates.X509KeyUsageFlags]($KeyUsage)) 155 | $KeyUsageObj.Critical = $true 156 | 157 | $cert.X509Extensions.Add($KeyUsageObj) 158 | $cert.X509Extensions.Add($ekuext) 159 | $cert.SignatureInformation.HashAlgorithm = $SigOID 160 | $CERT.X509Extensions.Add($SubjectAlternativeName) 161 | $cert.Encode() 162 | 163 | $enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1" 164 | $enrollment.InitializeFromRequest($cert) 165 | $certdata = $enrollment.CreateRequest(0) 166 | $enrollment.InstallResponse(2, $certdata, 0, "") 167 | 168 | # extract/return the thumbprint from the generated cert 169 | $parsed_cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 170 | $parsed_cert.Import([System.Text.Encoding]::UTF8.GetBytes($certdata)) 171 | 172 | return $parsed_cert.Thumbprint 173 | } 174 | 175 | Function Enable-GlobalHttpFirewallAccess { 176 | Write-Verbose "Forcing global HTTP firewall access" 177 | # this is a fairly naive implementation; could be more sophisticated about rule matching/collapsing 178 | $fw = New-Object -ComObject HNetCfg.FWPolicy2 179 | 180 | # try to find/enable the default rule first 181 | $add_rule = $false 182 | $matching_rules = $fw.Rules | Where-Object { $_.Name -eq "Windows Remote Management (HTTP-In)" } 183 | $rule = $null 184 | If ($matching_rules) { 185 | If ($matching_rules -isnot [Array]) { 186 | Write-Verbose "Editing existing single HTTP firewall rule" 187 | $rule = $matching_rules 188 | } 189 | Else { 190 | # try to find one with the All or Public profile first 191 | Write-Verbose "Found multiple existing HTTP firewall rules..." 192 | $rule = $matching_rules | ForEach-Object { $_.Profiles -band 4 }[0] 193 | 194 | If (-not $rule -or $rule -is [Array]) { 195 | Write-Verbose "Editing an arbitrary single HTTP firewall rule (multiple existed)" 196 | # oh well, just pick the first one 197 | $rule = $matching_rules[0] 198 | } 199 | } 200 | } 201 | 202 | If (-not $rule) { 203 | Write-Verbose "Creating a new HTTP firewall rule" 204 | $rule = New-Object -ComObject HNetCfg.FWRule 205 | $rule.Name = "Windows Remote Management (HTTP-In)" 206 | $rule.Description = "Inbound rule for Windows Remote Management via WS-Management. [TCP 5985]" 207 | $add_rule = $true 208 | } 209 | 210 | $rule.Profiles = 0x7FFFFFFF 211 | $rule.Protocol = 6 212 | $rule.LocalPorts = 5985 213 | $rule.RemotePorts = "*" 214 | $rule.LocalAddresses = "*" 215 | $rule.RemoteAddresses = "*" 216 | $rule.Enabled = $true 217 | $rule.Direction = 1 218 | $rule.Action = 1 219 | $rule.Grouping = "Windows Remote Management" 220 | 221 | If ($add_rule) { 222 | $fw.Rules.Add($rule) 223 | } 224 | 225 | Write-Verbose "HTTP firewall rule $($rule.Name) updated" 226 | } 227 | 228 | # Setup error handling. 229 | Trap { 230 | $_ 231 | Exit 1 232 | } 233 | $ErrorActionPreference = "Stop" 234 | 235 | # Get the ID and security principal of the current user account 236 | $myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent() 237 | $myWindowsPrincipal = new-object System.Security.Principal.WindowsPrincipal($myWindowsID) 238 | 239 | # Get the security principal for the Administrator role 240 | $adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator 241 | 242 | # Check to see if we are currently running "as Administrator" 243 | if (-Not $myWindowsPrincipal.IsInRole($adminRole)) { 244 | Write-Output "ERROR: You need elevated Administrator privileges in order to run this script." 245 | Write-Output " Start Windows PowerShell by using the Run as Administrator option." 246 | Exit 2 247 | } 248 | 249 | $EventSource = $MyInvocation.MyCommand.Name 250 | If (-Not $EventSource) { 251 | $EventSource = "Powershell CLI" 252 | } 253 | 254 | If ([System.Diagnostics.EventLog]::Exists('Application') -eq $False -or [System.Diagnostics.EventLog]::SourceExists($EventSource) -eq $False) { 255 | New-EventLog -LogName Application -Source $EventSource 256 | } 257 | 258 | # Detect PowerShell version. 259 | If ($PSVersionTable.PSVersion.Major -lt 3) { 260 | Write-ProgressLog "PowerShell version 3 or higher is required." 261 | Throw "PowerShell version 3 or higher is required." 262 | } 263 | 264 | # Find and start the WinRM service. 265 | Write-Verbose "Verifying WinRM service." 266 | If (!(Get-Service "WinRM")) { 267 | Write-ProgressLog "Unable to find the WinRM service." 268 | Throw "Unable to find the WinRM service." 269 | } 270 | ElseIf ((Get-Service "WinRM").Status -ne "Running") { 271 | Write-Verbose "Setting WinRM service to start automatically on boot." 272 | Set-Service -Name "WinRM" -StartupType Automatic 273 | Write-ProgressLog "Set WinRM service to start automatically on boot." 274 | Write-Verbose "Starting WinRM service." 275 | Start-Service -Name "WinRM" -ErrorAction Stop 276 | Write-ProgressLog "Started WinRM service." 277 | 278 | } 279 | 280 | # WinRM should be running; check that we have a PS session config. 281 | If (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\localhost\Listener))) { 282 | If ($SkipNetworkProfileCheck) { 283 | Write-Verbose "Enabling PS Remoting without checking Network profile." 284 | Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop 285 | Write-ProgressLog "Enabled PS Remoting without checking Network profile." 286 | } 287 | Else { 288 | Write-Verbose "Enabling PS Remoting." 289 | Enable-PSRemoting -Force -ErrorAction Stop 290 | Write-ProgressLog "Enabled PS Remoting." 291 | } 292 | } 293 | Else { 294 | Write-Verbose "PS Remoting is already enabled." 295 | } 296 | 297 | # Ensure LocalAccountTokenFilterPolicy is set to 1 298 | # https://github.com/ansible/ansible/issues/42978 299 | $token_path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" 300 | $token_prop_name = "LocalAccountTokenFilterPolicy" 301 | $token_key = Get-Item -Path $token_path 302 | $token_value = $token_key.GetValue($token_prop_name, $null) 303 | if ($token_value -ne 1) { 304 | Write-Verbose "Setting LocalAccountTOkenFilterPolicy to 1" 305 | if ($null -ne $token_value) { 306 | Remove-ItemProperty -Path $token_path -Name $token_prop_name 307 | } 308 | New-ItemProperty -Path $token_path -Name $token_prop_name -Value 1 -PropertyType DWORD > $null 309 | } 310 | 311 | # Make sure there is a SSL listener. 312 | $listeners = Get-ChildItem WSMan:\localhost\Listener 313 | If (!($listeners | Where-Object { $_.Keys -like "TRANSPORT=HTTPS" })) { 314 | # We cannot use New-SelfSignedCertificate on 2012R2 and earlier 315 | $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays 316 | Write-HostLog "Self-signed SSL certificate generated; thumbprint: $thumbprint" 317 | 318 | # Create the hashtables of settings to be used. 319 | $valueset = @{ 320 | Hostname = $SubjectName 321 | CertificateThumbprint = $thumbprint 322 | } 323 | 324 | $selectorset = @{ 325 | Transport = "HTTPS" 326 | Address = "*" 327 | } 328 | 329 | Write-Verbose "Enabling SSL listener." 330 | New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset 331 | Write-ProgressLog "Enabled SSL listener." 332 | } 333 | Else { 334 | Write-Verbose "SSL listener is already active." 335 | 336 | # Force a new SSL cert on Listener if the $ForceNewSSLCert 337 | If ($ForceNewSSLCert) { 338 | 339 | # We cannot use New-SelfSignedCertificate on 2012R2 and earlier 340 | $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays 341 | Write-HostLog "Self-signed SSL certificate generated; thumbprint: $thumbprint" 342 | 343 | $valueset = @{ 344 | CertificateThumbprint = $thumbprint 345 | Hostname = $SubjectName 346 | } 347 | 348 | # Delete the listener for SSL 349 | $selectorset = @{ 350 | Address = "*" 351 | Transport = "HTTPS" 352 | } 353 | Remove-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset 354 | 355 | # Add new Listener with new SSL cert 356 | New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset 357 | } 358 | } 359 | 360 | # Check for basic authentication. 361 | $basicAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where-Object { $_.Name -eq "Basic" } 362 | 363 | If ($DisableBasicAuth) { 364 | If (($basicAuthSetting.Value) -eq $true) { 365 | Write-Verbose "Disabling basic auth support." 366 | Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $false 367 | Write-ProgressLog "Disabled basic auth support." 368 | } 369 | Else { 370 | Write-Verbose "Basic auth is already disabled." 371 | } 372 | } 373 | Else { 374 | If (($basicAuthSetting.Value) -eq $false) { 375 | Write-Verbose "Enabling basic auth support." 376 | Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $true 377 | Write-ProgressLog "Enabled basic auth support." 378 | } 379 | Else { 380 | Write-Verbose "Basic auth is already enabled." 381 | } 382 | } 383 | 384 | # If EnableCredSSP if set to true 385 | If ($EnableCredSSP) { 386 | # Check for CredSSP authentication 387 | $credsspAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where-Object { $_.Name -eq "CredSSP" } 388 | If (($credsspAuthSetting.Value) -eq $false) { 389 | Write-Verbose "Enabling CredSSP auth support." 390 | Enable-WSManCredSSP -role server -Force 391 | Write-ProgressLog "Enabled CredSSP auth support." 392 | } 393 | } 394 | 395 | If ($GlobalHttpFirewallAccess) { 396 | Enable-GlobalHttpFirewallAccess 397 | } 398 | 399 | # Configure firewall to allow WinRM HTTPS connections. 400 | $fwtest1 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" 401 | $fwtest2 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" profile=any 402 | If ($fwtest1.count -lt 5) { 403 | Write-Verbose "Adding firewall rule to allow WinRM HTTPS." 404 | netsh advfirewall firewall add rule profile=any name="Allow WinRM HTTPS" dir=in localport=5986 protocol=TCP action=allow 405 | Write-ProgressLog "Added firewall rule to allow WinRM HTTPS." 406 | } 407 | ElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5)) { 408 | Write-Verbose "Updating firewall rule to allow WinRM HTTPS for any profile." 409 | netsh advfirewall firewall set rule name="Allow WinRM HTTPS" new profile=any 410 | Write-ProgressLog "Updated firewall rule to allow WinRM HTTPS for any profile." 411 | } 412 | Else { 413 | Write-Verbose "Firewall rule already exists to allow WinRM HTTPS." 414 | } 415 | 416 | # Test a remoting connection to localhost, which should work. 417 | $httpResult = Invoke-Command -ComputerName "localhost" -ScriptBlock { $using:env:COMPUTERNAME } -ErrorVariable httpError -ErrorAction SilentlyContinue 418 | $httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck 419 | 420 | $httpsResult = New-PSSession -UseSSL -ComputerName "localhost" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue 421 | 422 | If ($httpResult -and $httpsResult) { 423 | Write-Verbose "HTTP: Enabled | HTTPS: Enabled" 424 | } 425 | ElseIf ($httpsResult -and !$httpResult) { 426 | Write-Verbose "HTTP: Disabled | HTTPS: Enabled" 427 | } 428 | ElseIf ($httpResult -and !$httpsResult) { 429 | Write-Verbose "HTTP: Enabled | HTTPS: Disabled" 430 | } 431 | Else { 432 | Write-ProgressLog "Unable to establish an HTTP or HTTPS remoting session." 433 | Throw "Unable to establish an HTTP or HTTPS remoting session." 434 | } 435 | Write-VerboseLog "PS Remoting has been successfully configured for Ansible." 436 | -------------------------------------------------------------------------------- /.web-docs/components/builder/nutanix/README.md: -------------------------------------------------------------------------------- 1 | This document is going to detail all Nutanix plugin parameters. 2 | 3 | ## Principle 4 | The Nutanix plugin will create a temporary VM as foundation of your Packer image, apply all providers you define to customize your image, then clone the VM disk image as your final Packer image. 5 | 6 | ## Environment configuration 7 | These parameters allow to define information about platform and temporary VM used to create the image. 8 | 9 | ### Required 10 | - `nutanix_username` (string) - User used for Prism Central login. 11 | - `nutanix_password` (string) - Password of this user for Prism Central login. 12 | - `nutanix_endpoint` (string) - Prism Central FQDN or IP. 13 | - `cluster_name` or `cluster_uuid` (string) - Nutanix cluster name or uuid used to create and store image. 14 | - `os_type` (string) - OS Type ("Linux" or "Windows"). 15 | 16 | Starting `v1.1.4` the Nutanix Packer Plugin supports Prism Central Service Accounts. To use a Service Account, you need to provide `X-ntnx-api-key` as the `nutanix_username` and the corresponding API Key as the `nutanix_password`. 17 | 18 | ### Optional 19 | - `nutanix_port` (number) - Port used for connection to Prism Central. 20 | - `nutanix_insecure` (bool) - Authorize connection to Prism Central without valid certificate. 21 | - `vm_name` (string) - Name of the temporary VM to create. If not specified a random `packer-*` name will be used. 22 | - `cpu` (number) - Number of vCPU for temporary VM (default is 1). 23 | - `core` (number) - Number of cores per vCPU for temporary VM (default is 1). 24 | - `memory_mb` (number) - Size of vRAM for temporary VM (in megabytes). 25 | - `hardware_virtualization` (bool) - Enable hardware virtualization for temporary VM (default is false). 26 | - `cd_files` (array of strings) - A list of files to place onto a CD that is attached when the VM is booted. This can include either files or directories; any directories will be copied onto the CD recursively, preserving directory structure hierarchy. 27 | - `cd_label` (string) - Label of this CD Drive. 28 | - `boot_type` (string) - Type of boot used on the temporary VM ("legacy", "uefi" or "secure_boot", default is "legacy"). 29 | - `boot_priority` (string) - Priority of boot device ("cdrom" or "disk", default is "cdrom". UEFI support need AHV 8.0.12+, 9.1.1.2+, 9.1.3+, 9.2+ or 10.0+). 30 | - `vm_categories` ([]Category) - Assign Categories to the vm. 31 | - `project` (string) - Assign Project to the vm. 32 | - `gpu` ([] GPU) - GPU in cluster name to be attached on temporary VM. 33 | - `serialport` (bool) - Add a serial port to the temporary VM. This is required for some Linux Cloud Images that will have a kernel panic if a serial port is not present on first boot. 34 | 35 | #### vTPM 36 | 37 | Use `vtpm{}` entry to configure vTPM on the temporary VM. 38 | 39 | 40 | All parameters of this `vtpm` section are described below. 41 | 42 | - `enabled` (bool) - Enable vTPM for the temporary VM (default is false). 43 | 44 | 45 | Sample: 46 | ```hcl 47 | vtpm { 48 | enabled = true 49 | } 50 | ``` 51 | 52 | ## Output configuration 53 | These parameters allow to configure everything around image creation, from the temporary VM connection to the final image definition. 54 | 55 | ### All OS 56 | - `image_name` (string) - Name of the output image. 57 | - `image_description` (string) - Description for output image. 58 | - `image_categories` ([]Category) - Assign Categories to the image. 59 | - `force_deregister` (bool) - Allow output image override if already exists. 60 | - `image_delete` (bool) - Delete image once build process is completed (default is false). 61 | - `image_skip` (bool) - Skip image creation (default is false). 62 | - `image_export` (bool) - Export raw image in the current folder (default is false). 63 | - `fail_if_image_exists` (bool) - Fail the build if an image with the same name already exists (default is false). 64 | - `shutdown_command` (string) - Command line to shutdown your temporary VM. 65 | - `shutdown_timeout` (string) - Timeout for VM shutdown (format : 2m). 66 | - `vm_force_delete` (bool) - Delete vm even if build is not succesful (default is false). 67 | - `vm_retain` (bool) - Retain the temporary VM after build process is completed (default is false). 68 | - `disable_stop_instance` (bool) - When `true`, prevents Packer from automatically stopping the build instance after provisioning completes. Your final provisioner must handle stopping the instance, or the build will timeout (default is false). 69 | 70 | ### Dedicated to Linux 71 | - `user_data` (string) - cloud-init content base64 encoded. 72 | - `ssh_username` (string) - user for ssh connection initiated by Packer. 73 | - `ssh_password` (string) - password for the ssh user. 74 | 75 | ### Dedicated to Windows 76 | - `winrm_port` (number) - Port for WinRM communication (default is 5986). 77 | - `winrm_insecure` (bool) - Allow insecure connection to WinRM. 78 | - `winrm_use_ssl` (bool) - Request SSL connection with WinRM. 79 | - `winrm_timeout` (string) - Timeout for WinRM (format 45m). 80 | - `winrm_username` (string) - User login for WinRM connection. 81 | - `winrm_password` (string) - Password this User. 82 | 83 | ## Disk configuration 84 | Use `vm_disks{}` entry to configure disk to your VM image. If you want to configure several disks, use this entry multiple times. 85 | 86 | All parameters of this `vm_disks` section are described below. 87 | 88 | 3 types of disk configurations can be used: 89 | - disk (create an empty disk) 90 | - disk image (create disk from Nutanix image library) 91 | - ISO image (create disk from ISO image) 92 | 93 | ### Disk 94 | - `image_type` (string) - "DISK". 95 | - `disk_size_gb` (number) - size of th disk (in gigabytes). 96 | - `storage_container_uuid` (string) - UUID of the storage container where the disk image will be created. If not specified, the default storage container for the cluster will be used. 97 | 98 | 99 | Sample: 100 | ```hcl 101 | vm_disks { 102 | image_type = "DISK" 103 | disk_size_gb = 30 104 | } 105 | ``` 106 | 107 | ### Disk image 108 | - `image_type` (string) - "DISK_IMAGE" (you must use one of the three following parameters to source the image). 109 | - `source_image_name` (string) - Name of the image used as disk source. 110 | - `source_image_uuid` (string) - UUID of the image used as disk source. 111 | - `source_image_uri` (string) - URI of the image used as disk source (if image is not already on the cluster, it will download and store it before launching output image creation process). 112 | - `source_image_path` (string) - Path to the local image used as disk source (it will upload it before launching output image creation process). 113 | - `source_image_checksum` (string) - Checksum of the image used as disk source (work only with `source_image_uri` and if image is not already present in the library). 114 | - `source_image_checksum_type` (string) - Type of checksum used for `source_image_checksum` (`sha256` or `sha1` ). 115 | - `source_image_delete` (bool) - Delete image once build process is completed (default is false). 116 | - `source_image_force` (bool) - Always download and replace image even if already exist (default is false). 117 | - `disk_size_gb` (number) - size of the disk (in gigabytes). 118 | 119 | Sample: 120 | ```hcl 121 | vm_disks { 122 | image_type = "DISK_IMAGE" 123 | source_image_name = "<myDiskImage>" 124 | disk_size_gb = 40 125 | } 126 | ``` 127 | ### ISO Image 128 | - `image_type` (string) - "ISO_IMAGE". 129 | - `source_image_name` (string) - Name of the ISO image to mount. 130 | - `source_image_uuid` (string) - UUID of the ISO image to mount. 131 | - `source_image_uri` (string) - URI of the image used as ISO source (if image is not already on the cluster, it will download and store it before launching output image creation process). 132 | - `source_image_path` (string) - Path to the local image used as ISO source (it will upload it before launching output image creation process). 133 | - `source_image_checksum` (string) - Checksum of the image used as ISO source (work only with `source_image_uri` and if image is not already present in the library). 134 | - `source_image_checksum_type` (string) - Type of checksum used for `source_image_checksum` (`sha256` or `sha1` ). 135 | - `source_image_delete` (bool) - Delete source image once build process is completed (default is false). 136 | - `source_image_force` (bool) - Always download and replace source image even if already exist (default is false). 137 | 138 | Sample: 139 | ```hcl 140 | vm_disks { 141 | image_type = "ISO_IMAGE" 142 | source_image_name = "<myISOimage>" 143 | } 144 | ``` 145 | 146 | ## VM Clean 147 | 148 | Use `vm_clean{}` entry to configure VM cleaning options. This section allows you to clean up the temporary VM after the image creation process is completed. 149 | It can be useful to remove unnecessary components or reset the VM to a clean state before creating a template or exporting an OVA. 150 | 151 | All parameters of this `vm_clean` section are described below. 152 | 153 | - `cdrom` (bool) - Remove all CD-ROMs from the VM (default is false). 154 | 155 | Sample: 156 | ```hcl 157 | vm_clean { 158 | cdrom = true 159 | } 160 | ``` 161 | 162 | ## Template configuration 163 | 164 | Use `template{}` entry to create a template from the temporary VM. 165 | 166 | Template feature need Prism Central 2024.3+ or later. 167 | 168 | All parameters of this `template` section are described below. 169 | 170 | - `create` (bool) - Create a template from the temporary VM (default is false). 171 | - `name` (string) - Name of the template to create (default is the vm_name). 172 | - `description` (string) - Description of the template to create (default is no description). 173 | 174 | Sample: 175 | ```hcl 176 | template { 177 | create = true 178 | name = "myTemplate" 179 | description = "This is my template" 180 | } 181 | ``` 182 | 183 | ## OVA Config 184 | Use `ova{}` entry to configure the OVA creation & export 185 | 186 | All parameters of this `ova` section are described below. 187 | 188 | - `create` (bool) - Create OVA image for the vm (default is false). 189 | - `export` (bool) - Export OVA image in the current folder (default is false). 190 | - `format` (string) - Format of the ova image (allowed values: 'vmdk', 'qcow2', default 'vmdk'). 191 | - `name` (string) - Name of the the OVA image (default is the vm_name). 192 | 193 | Sample: 194 | ```hcl 195 | ova { 196 | create = true 197 | export = true 198 | format = "vmdk" 199 | name = "myExportedOVA" 200 | } 201 | ``` 202 | 203 | ## Network Configuration 204 | Use `vm_nics{}` entry to configure NICs in your image 205 | 206 | In this section, you have to define network you will to connect with one of this keyword : 207 | 208 | - `subnet_name` (string) - Name of the cluster subnet to use. 209 | - `subnet_uuid` (string) - UUID of the cluster subnet to use. 210 | - `mac_address` (string) - The network card MAC address. If not specified, a random MAC address will be generated. 211 | 212 | Sample 213 | ```hcl 214 | vm_nics { 215 | subnet_name = "<mySubnet>" 216 | } 217 | ``` 218 | 219 | ### Categories Configuration 220 | 221 | Use `image_categories{}` and `vm_categories{}` to assign category to your image or vm. If you want to assign multiple categories , use the entry multiple times. 222 | 223 | In this section, you have to define category you will to assign with the following parameters: 224 | 225 | - `key` (string) - Name of the category to assign. 226 | - `value` (string) - Value of the category to assign. 227 | 228 | Sample 229 | ```hcl 230 | image_categories { 231 | key = "OSType" 232 | value = "ubuntu-22.04" 233 | } 234 | ``` 235 | 236 | Note: Categories must already be present in Prism Central. 237 | 238 | ## GPU Configuration 239 | 240 | Use `GPU` to assign a GPU that is present on `cluster-name` on the temporary vm. Add the name of the GPU you wish to attach. 241 | 242 | Sample 243 | 244 | ```hcl 245 | gpu { 246 | name = "Ampere 40" 247 | } 248 | ``` 249 | 250 | ## Boot Configuration 251 | 252 | <!-- Code generated from the comments of the BootConfig struct in bootcommand/config.go; DO NOT EDIT MANUALLY --> 253 | 254 | The boot configuration is very important: `boot_command` specifies the keys 255 | to type when the virtual machine is first booted in order to start the OS 256 | installer. This command is typed after boot_wait, which gives the virtual 257 | machine some time to actually load. 258 | 259 | The boot_command is an array of strings. The strings are all typed in 260 | sequence. It is an array only to improve readability within the template. 261 | 262 | There are a set of special keys available. If these are in your boot 263 | command, they will be replaced by the proper key: 264 | 265 | - `<bs>` - Backspace 266 | 267 | - `<del>` - Delete 268 | 269 | - `<enter> <return>` - Simulates an actual "enter" or "return" keypress. 270 | 271 | - `<esc>` - Simulates pressing the escape key. 272 | 273 | - `<tab>` - Simulates pressing the tab key. 274 | 275 | - `<f1> - <f12>` - Simulates pressing a function key. 276 | 277 | - `<up> <down> <left> <right>` - Simulates pressing an arrow key. 278 | 279 | - `<spacebar>` - Simulates pressing the spacebar. 280 | 281 | - `<insert>` - Simulates pressing the insert key. 282 | 283 | - `<home> <end>` - Simulates pressing the home and end keys. 284 | 285 | - `<pageUp> <pageDown>` - Simulates pressing the page up and page down 286 | keys. 287 | 288 | - `<menu>` - Simulates pressing the Menu key. 289 | 290 | - `<leftAlt> <rightAlt>` - Simulates pressing the alt key. 291 | 292 | - `<leftCtrl> <rightCtrl>` - Simulates pressing the ctrl key. 293 | 294 | - `<leftShift> <rightShift>` - Simulates pressing the shift key. 295 | 296 | - `<leftSuper> <rightSuper>` - Simulates pressing the ⌘ or Windows key. 297 | 298 | - `<wait> <wait5> <wait10>` - Adds a 1, 5 or 10 second pause before 299 | sending any additional keys. This is useful if you have to generally 300 | wait for the UI to update before typing more. 301 | 302 | - `<waitXX>` - Add an arbitrary pause before sending any additional keys. 303 | The format of `XX` is a sequence of positive decimal numbers, each with 304 | optional fraction and a unit suffix, such as `300ms`, `1.5h` or `2h45m`. 305 | Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For 306 | example `<wait10m>` or `<wait1m20s>`. 307 | 308 | - `<XXXOn> <XXXOff>` - Any printable keyboard character, and of these 309 | "special" expressions, with the exception of the `<wait>` types, can 310 | also be toggled on or off. For example, to simulate ctrl+c, use 311 | `<leftCtrlOn>c<leftCtrlOff>`. Be sure to release them, otherwise they 312 | will be held down until the machine reboots. To hold the `c` key down, 313 | you would use `<cOn>`. Likewise, `<cOff>` to release. 314 | 315 | - `{{ .HTTPIP }} {{ .HTTPPort }}` - The IP and port, respectively of an 316 | HTTP server that is started serving the directory specified by the 317 | `http_directory` configuration parameter. If `http_directory` isn't 318 | specified, these will be blank! 319 | 320 | - `{{ .Name }}` - The name of the VM. 321 | 322 | Example boot command. This is actually a working boot command used to start an 323 | CentOS 6.4 installer: 324 | 325 | In JSON: 326 | 327 | ```json 328 | "boot_command": [ 329 | 330 | "<tab><wait>", 331 | " ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>" 332 | ] 333 | 334 | ``` 335 | 336 | In HCL2: 337 | 338 | ```hcl 339 | boot_command = [ 340 | 341 | "<tab><wait>", 342 | " ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>" 343 | ] 344 | 345 | ``` 346 | 347 | The example shown below is a working boot command used to start an Ubuntu 348 | 12.04 installer: 349 | 350 | In JSON: 351 | 352 | ```json 353 | "boot_command": [ 354 | 355 | "<esc><esc><enter><wait>", 356 | "/install/vmlinuz noapic ", 357 | "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ", 358 | "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ", 359 | "hostname={{ .Name }} ", 360 | "fb=false debconf/frontend=noninteractive ", 361 | "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ", 362 | "keyboard-configuration/variant=USA console-setup/ask_detect=false ", 363 | "initrd=/install/initrd.gz -- <enter>" 364 | 365 | ] 366 | ``` 367 | 368 | In HCL2: 369 | 370 | ```hcl 371 | boot_command = [ 372 | 373 | "<esc><esc><enter><wait>", 374 | "/install/vmlinuz noapic ", 375 | "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ", 376 | "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ", 377 | "hostname={{ .Name }} ", 378 | "fb=false debconf/frontend=noninteractive ", 379 | "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ", 380 | "keyboard-configuration/variant=USA console-setup/ask_detect=false ", 381 | "initrd=/install/initrd.gz -- <enter>" 382 | 383 | ] 384 | ``` 385 | 386 | For more examples of various boot commands, see the sample projects from our 387 | [community templates page](https://packer.io/community-tools#templates). 388 | 389 | <!-- End of code generated from the comments of the BootConfig struct in bootcommand/config.go; --> 390 | 391 | 392 | <!-- Code generated from the comments of the VNCConfig struct in bootcommand/config.go; DO NOT EDIT MANUALLY --> 393 | 394 | The boot command "typed" character for character over a VNC connection to 395 | the machine, simulating a human actually typing the keyboard. 396 | 397 | Keystrokes are typed as separate key up/down events over VNC with a default 398 | 100ms delay. The delay alleviates issues with latency and CPU contention. 399 | You can tune this delay on a per-builder basis by specifying 400 | "boot_key_interval" in your Packer template. 401 | 402 | <!-- End of code generated from the comments of the VNCConfig struct in bootcommand/config.go; --> 403 | 404 | 405 | **Optional**: 406 | 407 | <!-- Code generated from the comments of the BootConfig struct in bootcommand/config.go; DO NOT EDIT MANUALLY --> 408 | 409 | - `boot_keygroup_interval` (duration string | ex: "1h5m2s") - Time to wait after sending a group of key pressses. The value of this 410 | should be a duration. Examples are `5s` and `1m30s` which will cause 411 | Packer to wait five seconds and one minute 30 seconds, respectively. If 412 | this isn't specified, a sensible default value is picked depending on 413 | the builder type. 414 | 415 | - `boot_wait` (duration string | ex: "1h5m2s") - The time to wait after booting the initial virtual machine before typing 416 | the `boot_command`. The value of this should be a duration. Examples are 417 | `5s` and `1m30s` which will cause Packer to wait five seconds and one 418 | minute 30 seconds, respectively. If this isn't specified, the default is 419 | `10s` or 10 seconds. To set boot_wait to 0s, use a negative number, such 420 | as "-1s" 421 | 422 | - `boot_command` ([]string) - This is an array of commands to type when the virtual machine is first 423 | booted. The goal of these commands should be to type just enough to 424 | initialize the operating system installer. Special keys can be typed as 425 | well, and are covered in the section below on the boot command. If this 426 | is not specified, it is assumed the installer will start itself. 427 | 428 | <!-- End of code generated from the comments of the BootConfig struct in bootcommand/config.go; --> 429 | 430 | 431 | <!-- Code generated from the comments of the VNCConfig struct in bootcommand/config.go; DO NOT EDIT MANUALLY --> 432 | 433 | - `disable_vnc` (bool) - Whether to create a VNC connection or not. A boot_command cannot be used 434 | when this is true. Defaults to false. 435 | 436 | - `boot_key_interval` (duration string | ex: "1h5m2s") - Time in ms to wait between each key press 437 | 438 | <!-- End of code generated from the comments of the VNCConfig struct in bootcommand/config.go; --> 439 | 440 | 441 | ## IP Wait configuration 442 | 443 | **Optional**: 444 | 445 | <!-- Code generated from the comments of the WaitIpConfig struct in builder/nutanix/step_wait_for_ip.go; DO NOT EDIT MANUALLY --> 446 | 447 | - `ip_wait_timeout` (duration string | ex: "1h5m2s") - Amount of time to wait for VM's IP, similar to 'ssh_timeout'. 448 | Defaults to `30m` (30 minutes). Refer to the Golang 449 | [ParseDuration](https://golang.org/pkg/time/#ParseDuration) 450 | documentation for full details. 451 | 452 | - `ip_settle_timeout` (duration string | ex: "1h5m2s") - Amount of time to wait for VM's IP to settle down, sometimes VM may 453 | report incorrect IP initially, then it is recommended to set that 454 | parameter to apx. 2 minutes. Examples `45s` and `10m`. 455 | Defaults to `5s` (5 seconds). Refer to the Golang 456 | [ParseDuration](https://golang.org/pkg/time/#ParseDuration) 457 | documentation for full details. 458 | 459 | - `ip_wait_address` (\*string) - Set this to a CIDR address to cause the service to wait for an address that is contained in 460 | this network range. Defaults to `0.0.0.0/0` for any IPv4 address. Examples include: 461 | 462 | * empty string ("") - remove all filters 463 | * `0:0:0:0:0:0:0:0/0` - allow only ipv6 addresses 464 | * `192.168.1.0/24` - only allow ipv4 addresses from 192.168.1.1 to 192.168.1.254 465 | 466 | <!-- End of code generated from the comments of the WaitIpConfig struct in builder/nutanix/step_wait_for_ip.go; --> 467 | 468 | 469 | ## Communicator Configuration 470 | 471 | **Optional**: 472 | 473 | ##### Common 474 | 475 | <!-- Code generated from the comments of the Config struct in communicator/config.go; DO NOT EDIT MANUALLY --> 476 | 477 | - `communicator` (string) - Packer currently supports three kinds of communicators: 478 | 479 | - `none` - No communicator will be used. If this is set, most 480 | provisioners also can't be used. 481 | 482 | - `ssh` - An SSH connection will be established to the machine. This 483 | is usually the default. 484 | 485 | - `winrm` - A WinRM connection will be established. 486 | 487 | In addition to the above, some builders have custom communicators they 488 | can use. For example, the Docker builder has a "docker" communicator 489 | that uses `docker exec` and `docker cp` to execute scripts and copy 490 | files. 491 | 492 | - `pause_before_connecting` (duration string | ex: "1h5m2s") - We recommend that you enable SSH or WinRM as the very last step in your 493 | guest's bootstrap script, but sometimes you may have a race condition 494 | where you need Packer to wait before attempting to connect to your 495 | guest. 496 | 497 | If you end up in this situation, you can use the template option 498 | `pause_before_connecting`. By default, there is no pause. For example if 499 | you set `pause_before_connecting` to `10m` Packer will check whether it 500 | can connect, as normal. But once a connection attempt is successful, it 501 | will disconnect and then wait 10 minutes before connecting to the guest 502 | and beginning provisioning. 503 | 504 | <!-- End of code generated from the comments of the Config struct in communicator/config.go; --> 505 | 506 | 507 | ##### SSH 508 | 509 | <!-- Code generated from the comments of the SSH struct in communicator/config.go; DO NOT EDIT MANUALLY --> 510 | 511 | - `ssh_host` (string) - The address to SSH to. This usually is automatically configured by the 512 | builder. 513 | 514 | - `ssh_port` (int) - The port to connect to SSH. This defaults to `22`. 515 | 516 | - `ssh_username` (string) - The username to connect to SSH with. Required if using SSH. 517 | 518 | - `ssh_password` (string) - A plaintext password to use to authenticate with SSH. 519 | 520 | - `ssh_ciphers` ([]string) - This overrides the value of ciphers supported by default by Golang. 521 | The default value is [ 522 | "aes128-gcm@openssh.com", 523 | "chacha20-poly1305@openssh.com", 524 | "aes128-ctr", "aes192-ctr", "aes256-ctr", 525 | ] 526 | 527 | Valid options for ciphers include: 528 | "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", 529 | "chacha20-poly1305@openssh.com", 530 | "arcfour256", "arcfour128", "arcfour", "aes128-cbc", "3des-cbc", 531 | 532 | - `ssh_clear_authorized_keys` (bool) - If true, Packer will attempt to remove its temporary key from 533 | `~/.ssh/authorized_keys` and `/root/.ssh/authorized_keys`. This is a 534 | mostly cosmetic option, since Packer will delete the temporary private 535 | key from the host system regardless of whether this is set to true 536 | (unless the user has set the `-debug` flag). Defaults to "false"; 537 | currently only works on guests with `sed` installed. 538 | 539 | - `ssh_key_exchange_algorithms` ([]string) - If set, Packer will override the value of key exchange (kex) algorithms 540 | supported by default by Golang. Acceptable values include: 541 | "curve25519-sha256@libssh.org", "ecdh-sha2-nistp256", 542 | "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", 543 | "diffie-hellman-group14-sha1", and "diffie-hellman-group1-sha1". 544 | 545 | - `ssh_certificate_file` (string) - Path to user certificate used to authenticate with SSH. 546 | The `~` can be used in path and will be expanded to the 547 | home directory of current user. 548 | 549 | - `ssh_pty` (bool) - If `true`, a PTY will be requested for the SSH connection. This defaults 550 | to `false`. 551 | 552 | - `ssh_timeout` (duration string | ex: "1h5m2s") - The time to wait for SSH to become available. Packer uses this to 553 | determine when the machine has booted so this is usually quite long. 554 | Example value: `10m`. 555 | This defaults to `5m`, unless `ssh_handshake_attempts` is set. 556 | 557 | - `ssh_disable_agent_forwarding` (bool) - If true, SSH agent forwarding will be disabled. Defaults to `false`. 558 | 559 | - `ssh_handshake_attempts` (int) - The number of handshakes to attempt with SSH once it can connect. 560 | This defaults to `10`, unless a `ssh_timeout` is set. 561 | 562 | - `ssh_bastion_host` (string) - A bastion host to use for the actual SSH connection. 563 | 564 | - `ssh_bastion_port` (int) - The port of the bastion host. Defaults to `22`. 565 | 566 | - `ssh_bastion_agent_auth` (bool) - If `true`, the local SSH agent will be used to authenticate with the 567 | bastion host. Defaults to `false`. 568 | 569 | - `ssh_bastion_username` (string) - The username to connect to the bastion host. 570 | 571 | - `ssh_bastion_password` (string) - The password to use to authenticate with the bastion host. 572 | 573 | - `ssh_bastion_interactive` (bool) - If `true`, the keyboard-interactive used to authenticate with bastion host. 574 | 575 | - `ssh_bastion_private_key_file` (string) - Path to a PEM encoded private key file to use to authenticate with the 576 | bastion host. The `~` can be used in path and will be expanded to the 577 | home directory of current user. 578 | 579 | - `ssh_bastion_certificate_file` (string) - Path to user certificate used to authenticate with bastion host. 580 | The `~` can be used in path and will be expanded to the 581 | home directory of current user. 582 | 583 | - `ssh_file_transfer_method` (string) - `scp` or `sftp` - How to transfer files, Secure copy (default) or SSH 584 | File Transfer Protocol. 585 | 586 | **NOTE**: Guests using Windows with Win32-OpenSSH v9.1.0.0p1-Beta, scp 587 | (the default protocol for copying data) returns a a non-zero error code since the MOTW 588 | cannot be set, which cause any file transfer to fail. As a workaround you can override the transfer protocol 589 | with SFTP instead `ssh_file_transfer_method = "sftp"`. 590 | 591 | - `ssh_proxy_host` (string) - A SOCKS proxy host to use for SSH connection 592 | 593 | - `ssh_proxy_port` (int) - A port of the SOCKS proxy. Defaults to `1080`. 594 | 595 | - `ssh_proxy_username` (string) - The optional username to authenticate with the proxy server. 596 | 597 | - `ssh_proxy_password` (string) - The optional password to use to authenticate with the proxy server. 598 | 599 | - `ssh_keep_alive_interval` (duration string | ex: "1h5m2s") - How often to send "keep alive" messages to the server. Set to a negative 600 | value (`-1s`) to disable. Example value: `10s`. Defaults to `5s`. 601 | 602 | - `ssh_read_write_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait for a remote command to end. This might be 603 | useful if, for example, packer hangs on a connection after a reboot. 604 | Example: `5m`. Disabled by default. 605 | 606 | - `ssh_remote_tunnels` ([]string) - Remote tunnels forward a port from your local machine to the instance. 607 | Format: ["REMOTE_PORT:LOCAL_HOST:LOCAL_PORT"] 608 | Example: "9090:localhost:80" forwards localhost:9090 on your machine to port 80 on the instance. 609 | 610 | - `ssh_local_tunnels` ([]string) - Local tunnels forward a port from the instance to your local machine. 611 | Format: ["LOCAL_PORT:REMOTE_HOST:REMOTE_PORT"] 612 | Example: "8080:localhost:3000" allows the instance to access your local machine’s port 3000 via localhost:8080. 613 | 614 | <!-- End of code generated from the comments of the SSH struct in communicator/config.go; --> 615 | 616 | 617 | - `ssh_private_key_file` (string) - Path to a PEM encoded private key file to use to authenticate with SSH. 618 | The `~` can be used in path and will be expanded to the home directory 619 | of current user. 620 | 621 | 622 | ##### Windows Remote Management (WinRM) 623 | 624 | <!-- Code generated from the comments of the WinRM struct in communicator/config.go; DO NOT EDIT MANUALLY --> 625 | 626 | - `winrm_username` (string) - The username to use to connect to WinRM. 627 | 628 | - `winrm_password` (string) - The password to use to connect to WinRM. 629 | 630 | - `winrm_host` (string) - The address for WinRM to connect to. 631 | 632 | NOTE: If using an Amazon EBS builder, you can specify the interface 633 | WinRM connects to via 634 | [`ssh_interface`](/packer/integrations/nutanix-cloud-native/amazon/latest/components/builder/ebs#ssh_interface) 635 | 636 | - `winrm_no_proxy` (bool) - Setting this to `true` adds the remote 637 | `host:port` to the `NO_PROXY` environment variable. This has the effect of 638 | bypassing any configured proxies when connecting to the remote host. 639 | Default to `false`. 640 | 641 | - `winrm_port` (int) - The WinRM port to connect to. This defaults to `5985` for plain 642 | unencrypted connection and `5986` for SSL when `winrm_use_ssl` is set to 643 | true. 644 | 645 | - `winrm_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait for WinRM to become available. This defaults 646 | to `30m` since setting up a Windows machine generally takes a long time. 647 | 648 | - `winrm_use_ssl` (bool) - If `true`, use HTTPS for WinRM. 649 | 650 | - `winrm_insecure` (bool) - If `true`, do not check server certificate chain and host name. 651 | 652 | - `winrm_use_ntlm` (bool) - If `true`, NTLMv2 authentication (with session security) will be used 653 | for WinRM, rather than default (basic authentication), removing the 654 | requirement for basic authentication to be enabled within the target 655 | guest. Further reading for remote connection authentication can be found 656 | [here](https://msdn.microsoft.com/en-us/library/aa384295(v=vs.85).aspx). 657 | 658 | <!-- End of code generated from the comments of the WinRM struct in communicator/config.go; --> 659 | 660 | 661 | ## Samples 662 | 663 | You can find samples [here](https://github.com/nutanix-cloud-native/packer-plugin-nutanix/tree/main/example) for these instructions usage. 664 | --------------------------------------------------------------------------------