UNPKG

@muhlba91/pulumi-proxmoxve

Version:

A Pulumi package for creating and managing Proxmox Virtual Environment cloud resources.

426 lines 20.3 kB
"use strict"; // *** WARNING: this file was generated by pulumi-language-nodejs. *** // *** Do not edit by hand unless you're certain you know what you are doing! *** var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VmLegacy = void 0; const pulumi = __importStar(require("@pulumi/pulumi")); const utilities = __importStar(require("./utilities")); /** * Manages a virtual machine. * * ## Example Usage * * ```typescript * import * as pulumi from "@pulumi/pulumi"; * import * as proxmoxve from "@muhlba91/pulumi-proxmoxve"; * import * as random from "@pulumi/random"; * import * as std from "@pulumi/std"; * import * as tls from "@pulumi/tls"; * * export = async () => { * const latestUbuntu22JammyQcow2Img = new proxmoxve.download.FileLegacy("latest_ubuntu_22_jammy_qcow2_img", { * contentType: "import", * datastoreId: "local", * nodeName: "pve", * url: "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img", * fileName: "jammy-server-cloudimg-amd64.qcow2", * }); * const ubuntuVmPassword = new random.RandomPassword("ubuntu_vm_password", { * length: 16, * overrideSpecial: "_%@", * special: true, * }); * const ubuntuVmKey = new tls.PrivateKey("ubuntu_vm_key", { * algorithm: "RSA", * rsaBits: 2048, * }); * const ubuntuVm = new proxmoxve.VmLegacy("ubuntu_vm", { * serialDevices: [{}], * name: "terraform-provider-proxmox-ubuntu-vm", * description: "Managed by Pulumi", * tags: [ * "terraform", * "ubuntu", * ], * nodeName: "first-node", * vmId: 4321, * agent: { * enabled: false, * }, * stopOnDestroy: true, * startup: { * order: 3, * upDelay: 60, * downDelay: 60, * }, * cpu: { * cores: 2, * type: "x86-64-v2-AES", * }, * memory: { * dedicated: 2048, * floating: 2048, * }, * disks: [{ * datastoreId: "local-lvm", * importFrom: latestUbuntu22JammyQcow2Img.id, * "interface": "scsi0", * }], * initialization: { * ipConfigs: [{ * ipv4: { * address: "dhcp", * }, * }], * userAccount: { * keys: [std.trimspaceOutput({ * input: ubuntuVmKey.publicKeyOpenssh, * }).apply(invoke => invoke.result)], * password: ubuntuVmPassword.result, * username: "ubuntu", * }, * userDataFileId: cloudConfig.id, * }, * networkDevices: [{ * bridge: "vmbr0", * }], * operatingSystem: { * type: "l26", * }, * tpmState: { * version: "v2.0", * }, * virtiofs: [{ * mapping: "data_share", * cache: "always", * directIo: true, * }], * }); * return { * ubuntuVmPassword: ubuntuVmPassword.result, * ubuntuVmPrivateKey: ubuntuVmKey.privateKeyPem, * ubuntuVmPublicKey: ubuntuVmKey.publicKeyOpenssh, * }; * } * ``` * * ## Qemu guest agent * * Qemu-guest-agent is an application which can be installed inside guest VM, see * [Proxmox Wiki](https://pve.proxmox.com/wiki/Qemu-guest-agent) and [Proxmox * Documentation](https://pve.proxmox.com/pve-docs/pve-admin-guide.html#qm_qemu_agent) * * For VM with `agent.enabled = false`, Proxmox uses ACPI for `Shutdown` and * `Reboot`, and `qemu-guest-agent` is not needed inside the VM. For some VMs, * the shutdown process may not work, causing the VM to be stuck on destroying. * Add `stopOnDestroy = true` to the VM configuration to stop the VM instead of * shutting it down. * * Setting `agent.enabled = true` informs Proxmox that the guest agent is expected * to be *running* inside the VM. Proxmox then uses `qemu-guest-agent` instead of * ACPI to control the VM. If the agent is not running, Proxmox operations * `Shutdown` and `Reboot` time out and fail. The failing operation gets a lock on * the VM, and until the operation times out, other operations like `Stop` and * `Reboot` cannot be used. * * Do **not** run VM with `agent.enabled = true`, unless the VM is configured to * automatically **start** `qemu-guest-agent` at some point. * * "Monitor" tab in Proxmox GUI can be used to send low-level commands to `qemu`. * See the [documentation](https://www.qemu.org/docs/master/system/monitor.html). * Commands `systemPowerdown` and `quit` have proven useful in shutting down VMs * with `agent.enabled = true` and no agent running. * * Cloud images usually do not have `qemu-guest-agent` installed. It is possible to * install and *start* it using cloud-init, e.g. using custom `userDataFileId` * file. * * This provider requires `agent.enabled = true` to populate `ipv4Addresses`, * `ipv6Addresses` and `networkInterfaceNames` output attributes. * * Setting `agent.enabled = true` without running `qemu-guest-agent` in the VM will * also result in long timeouts when using the provider, both when creating VMs, * and when refreshing resources. The provider has no way to distinguish between * "qemu-guest-agent not installed" and "very long boot due to a disk check", it * trusts the user to set `agent.enabled` correctly and waits for * `qemu-guest-agent` to start. * * ## AMD SEV * * AMD SEV (-ES, -SNP) are security features for AMD processors. SEV-SNP support * is included in Proxmox version **8.4**, see Proxmox Wiki * and [Proxmox Documentation](https://pve.proxmox.com/pve-docs/pve-admin-guide.html#qm_memory_encryption) * for more information. * * `amd-sev` requires root and therefore `root@pam` auth. * * SEV-SNP requires `bios = OVMF` and a supported AMD CPU (`EPYC-v4` for instance), `machine = q35` is also advised. No EFI disk is required since SEV-SNP uses consolidated read-only firmware. A configured EFI will be ignored. * * All changes made to `amdSev` will trigger reboots. Removing or adding the `amdSev` block will force a replacement of the resource. Modifying the `amdSev` block will not trigger replacements. * * `allowSmt` is by default set to `true` even if `snp` is not the selected type. Proxmox will ignore this value when `snp` is not in use. Likewise `noKeySharing` is `false` by default but ignored by Proxmox when `snp` is in use. * * ## High Availability * * When managing a virtual machine in a multi-node cluster, the VM's HA settings can * be managed using the `proxmoxve.HaresourceLegacy` resource. * * ```typescript * import * as pulumi from "@pulumi/pulumi"; * import * as proxmoxve from "@muhlba91/pulumi-proxmoxve"; * * const ubuntuVm = new proxmoxve.VmLegacy("ubuntu_vm", { * name: "terraform-provider-proxmox-ubuntu-vm", * vmId: 4321, * }); * const ubuntuVmHaresourceLegacy = new proxmoxve.HaresourceLegacy("ubuntu_vm", { * resourceId: pulumi.interpolate`vm:${ubuntuVm.vmId}`, * group: "node1", * state: "started", * comment: "Managed by Pulumi", * }); * ``` * * ### HA-Aware Migration * * When changing the `nodeName` of an HA-managed VM, the provider automatically * handles the migration in an HA-aware manner: * * - **Running HA VMs**: Uses the HA manager's migrate endpoint for live migration * - **Stopped HA VMs**: Temporarily removes from HA, performs standard migration, * then re-adds to HA with the original configuration preserved * * > **PVE 9.x Required**: HA-aware migration requires Proxmox VE 9.x due to API * changes. On PVE 8.x, migrating HA-managed VMs will fail. As a workaround, * manually remove the VM from HA before changing `nodeName`, then re-add after * apply. * * ## Important Notes * * ### `local-lvm` Datastore * * The `local-lvm` is the **default datastore** for many configuration blocks, including `initialization` and `tpmState`, which may not seem to be related to "storage". * If you do not have `local-lvm` configured in your environment, you may need to explicitly set the `datastoreId` in such blocks to a different value. * * ### Cloning * * When cloning an existing virtual machine, whether it's a template or not, the * resource will inherit the disks and other configuration from the source VM. * * *If* you modify any attributes of an existing disk in the clone, you also need to\ * explicitly provide values for any other attributes that differ from the schema defaults\ * in the source (e.g., `size`, `discard`, `cache`, `aio`).\ * Otherwise, the schema defaults will take effect and override the source values. * * Furthermore, when cloning from one node to a different one, the behavior changes * depening on the datastores of the source VM. If at least one non-shared * datastore is used, the VM is first cloned to the source node before being * migrated to the target node. This circumvents a limitation in the Proxmox clone * API. * * Because the migration step after the clone tries to preserve the used * datastores by their name, it may fail if a datastore used in the source VM is * not available on the target node (e.g. `local-lvm` is used on the source node in * the VM but no `local-lvm` datastore is available on the target node). In this * case, it is recommended to set the `datastoreId` argument in the `clone` block * to force the migration step to migrate all disks to a specific datastore on the * target node. If you need certain disks to be on specific datastores, set * the `datastoreId` argument of the disks in the `disks` block to move the disks * to the correct datastore after the cloning and migrating succeeded. * * ## Import * * Instances can be imported using the `nodeName` and the `vmId`, e.g., * * ```sh * $ pulumi import proxmoxve:index/vmLegacy:VmLegacy ubuntu_vm first-node/4321 * ``` */ class VmLegacy extends pulumi.CustomResource { /** * Get an existing VmLegacy resource's state with the given name, ID, and optional extra * properties used to qualify the lookup. * * @param name The _unique_ name of the resulting resource. * @param id The _unique_ provider ID of the resource to lookup. * @param state Any extra arguments used during the lookup. * @param opts Optional settings to control the behavior of the CustomResource. */ static get(name, id, state, opts) { return new VmLegacy(name, state, { ...opts, id: id }); } /** @internal */ static __pulumiType = 'proxmoxve:index/vmLegacy:VmLegacy'; /** * Returns true if the given object is an instance of VmLegacy. This is designed to work even * when multiple copies of the Pulumi SDK have been loaded into the same process. */ static isInstance(obj) { if (obj === undefined || obj === null) { return false; } return obj['__pulumiType'] === VmLegacy.__pulumiType; } constructor(name, argsOrState, opts) { let resourceInputs = {}; opts = opts || {}; if (opts.id) { const state = argsOrState; resourceInputs["acpi"] = state?.acpi; resourceInputs["agent"] = state?.agent; resourceInputs["amdSev"] = state?.amdSev; resourceInputs["audioDevice"] = state?.audioDevice; resourceInputs["bios"] = state?.bios; resourceInputs["bootOrders"] = state?.bootOrders; resourceInputs["cdrom"] = state?.cdrom; resourceInputs["clone"] = state?.clone; resourceInputs["cpu"] = state?.cpu; resourceInputs["deleteUnreferencedDisksOnDestroy"] = state?.deleteUnreferencedDisksOnDestroy; resourceInputs["description"] = state?.description; resourceInputs["disks"] = state?.disks; resourceInputs["efiDisk"] = state?.efiDisk; resourceInputs["hookScriptFileId"] = state?.hookScriptFileId; resourceInputs["hostpcis"] = state?.hostpcis; resourceInputs["hotplug"] = state?.hotplug; resourceInputs["initialization"] = state?.initialization; resourceInputs["ipv4Addresses"] = state?.ipv4Addresses; resourceInputs["ipv6Addresses"] = state?.ipv6Addresses; resourceInputs["keyboardLayout"] = state?.keyboardLayout; resourceInputs["kvmArguments"] = state?.kvmArguments; resourceInputs["macAddresses"] = state?.macAddresses; resourceInputs["machine"] = state?.machine; resourceInputs["memory"] = state?.memory; resourceInputs["migrate"] = state?.migrate; resourceInputs["name"] = state?.name; resourceInputs["networkDevices"] = state?.networkDevices; resourceInputs["networkInterfaceNames"] = state?.networkInterfaceNames; resourceInputs["nodeName"] = state?.nodeName; resourceInputs["numas"] = state?.numas; resourceInputs["onBoot"] = state?.onBoot; resourceInputs["operatingSystem"] = state?.operatingSystem; resourceInputs["poolId"] = state?.poolId; resourceInputs["protection"] = state?.protection; resourceInputs["purgeOnDestroy"] = state?.purgeOnDestroy; resourceInputs["reboot"] = state?.reboot; resourceInputs["rebootAfterUpdate"] = state?.rebootAfterUpdate; resourceInputs["rngs"] = state?.rngs; resourceInputs["scsiHardware"] = state?.scsiHardware; resourceInputs["serialDevices"] = state?.serialDevices; resourceInputs["smbios"] = state?.smbios; resourceInputs["started"] = state?.started; resourceInputs["startup"] = state?.startup; resourceInputs["stopOnDestroy"] = state?.stopOnDestroy; resourceInputs["tabletDevice"] = state?.tabletDevice; resourceInputs["tags"] = state?.tags; resourceInputs["template"] = state?.template; resourceInputs["timeoutClone"] = state?.timeoutClone; resourceInputs["timeoutCreate"] = state?.timeoutCreate; resourceInputs["timeoutMigrate"] = state?.timeoutMigrate; resourceInputs["timeoutMoveDisk"] = state?.timeoutMoveDisk; resourceInputs["timeoutReboot"] = state?.timeoutReboot; resourceInputs["timeoutShutdownVm"] = state?.timeoutShutdownVm; resourceInputs["timeoutStartVm"] = state?.timeoutStartVm; resourceInputs["timeoutStopVm"] = state?.timeoutStopVm; resourceInputs["tpmState"] = state?.tpmState; resourceInputs["usbs"] = state?.usbs; resourceInputs["vga"] = state?.vga; resourceInputs["virtiofs"] = state?.virtiofs; resourceInputs["vmId"] = state?.vmId; resourceInputs["watchdog"] = state?.watchdog; } else { const args = argsOrState; if (args?.nodeName === undefined && !opts.urn) { throw new Error("Missing required property 'nodeName'"); } resourceInputs["acpi"] = args?.acpi; resourceInputs["agent"] = args?.agent; resourceInputs["amdSev"] = args?.amdSev; resourceInputs["audioDevice"] = args?.audioDevice; resourceInputs["bios"] = args?.bios; resourceInputs["bootOrders"] = args?.bootOrders; resourceInputs["cdrom"] = args?.cdrom; resourceInputs["clone"] = args?.clone; resourceInputs["cpu"] = args?.cpu; resourceInputs["deleteUnreferencedDisksOnDestroy"] = args?.deleteUnreferencedDisksOnDestroy; resourceInputs["description"] = args?.description; resourceInputs["disks"] = args?.disks; resourceInputs["efiDisk"] = args?.efiDisk; resourceInputs["hookScriptFileId"] = args?.hookScriptFileId; resourceInputs["hostpcis"] = args?.hostpcis; resourceInputs["hotplug"] = args?.hotplug; resourceInputs["initialization"] = args?.initialization; resourceInputs["keyboardLayout"] = args?.keyboardLayout; resourceInputs["kvmArguments"] = args?.kvmArguments; resourceInputs["macAddresses"] = args?.macAddresses; resourceInputs["machine"] = args?.machine; resourceInputs["memory"] = args?.memory; resourceInputs["migrate"] = args?.migrate; resourceInputs["name"] = args?.name; resourceInputs["networkDevices"] = args?.networkDevices; resourceInputs["nodeName"] = args?.nodeName; resourceInputs["numas"] = args?.numas; resourceInputs["onBoot"] = args?.onBoot; resourceInputs["operatingSystem"] = args?.operatingSystem; resourceInputs["poolId"] = args?.poolId; resourceInputs["protection"] = args?.protection; resourceInputs["purgeOnDestroy"] = args?.purgeOnDestroy; resourceInputs["reboot"] = args?.reboot; resourceInputs["rebootAfterUpdate"] = args?.rebootAfterUpdate; resourceInputs["rngs"] = args?.rngs; resourceInputs["scsiHardware"] = args?.scsiHardware; resourceInputs["serialDevices"] = args?.serialDevices; resourceInputs["smbios"] = args?.smbios; resourceInputs["started"] = args?.started; resourceInputs["startup"] = args?.startup; resourceInputs["stopOnDestroy"] = args?.stopOnDestroy; resourceInputs["tabletDevice"] = args?.tabletDevice; resourceInputs["tags"] = args?.tags; resourceInputs["template"] = args?.template; resourceInputs["timeoutClone"] = args?.timeoutClone; resourceInputs["timeoutCreate"] = args?.timeoutCreate; resourceInputs["timeoutMigrate"] = args?.timeoutMigrate; resourceInputs["timeoutMoveDisk"] = args?.timeoutMoveDisk; resourceInputs["timeoutReboot"] = args?.timeoutReboot; resourceInputs["timeoutShutdownVm"] = args?.timeoutShutdownVm; resourceInputs["timeoutStartVm"] = args?.timeoutStartVm; resourceInputs["timeoutStopVm"] = args?.timeoutStopVm; resourceInputs["tpmState"] = args?.tpmState; resourceInputs["usbs"] = args?.usbs; resourceInputs["vga"] = args?.vga; resourceInputs["virtiofs"] = args?.virtiofs; resourceInputs["vmId"] = args?.vmId; resourceInputs["watchdog"] = args?.watchdog; resourceInputs["ipv4Addresses"] = undefined /*out*/; resourceInputs["ipv6Addresses"] = undefined /*out*/; resourceInputs["networkInterfaceNames"] = undefined /*out*/; } opts = pulumi.mergeOptions(utilities.resourceOptsDefaults(), opts); super(VmLegacy.__pulumiType, name, resourceInputs, opts); } } exports.VmLegacy = VmLegacy; //# sourceMappingURL=vmLegacy.js.map