Author SHA1 Message Date
christianmanivong 6c4ff65710 Merge feature/node-scoped-image-storage: get_image_storages() + storage param 2026-07-07 22:35:35 +02:00
christianmanivong f9b8a54673 feat(hypervisor): add StorageTargetDict and get_image_storages(), storage param on create_vm_from_cloud_init
Lets callers select which node-available storage pool a new VM's root
disk lands on, instead of always trusting the driver's auto-detected
default.
2026-07-07 22:35:33 +02:00
christianmanivong d9a23e08f2 Merge feature/create-vm-from-image: create_vm_from_cloud_init downloads images directly 2026-07-07 10:38:03 +02:00
christianmanivong 5059df6b25 feat(hypervisor): create_vm_from_cloud_init downloads a cloud image directly
Replaces template-clone semantics (template: str, existing Proxmox template
VMID) with image_url: str — the driver now downloads the cloud image itself
and imports it as the VM's root disk, rather than requiring an admin to have
pre-built a template. Adds image_checksum for optional verification and a
separate download_timeout since image downloads can take much longer than
the rest of provisioning.
2026-07-07 10:25:45 +02:00
christianmanivong a37dc8d632 Merge feature/network-target-vlan-tag: expose fixed VLAN tag for SDN vnets 2026-07-07 10:20:42 +02:00
christianmanivong cb274156a4 feat(models): add fixed_vlan_tag to NetworkTargetDict for SDN vnets 2026-07-07 10:20:36 +02:00
christianmanivong a16ca77156 Merge feature/network-targets: add get_network_targets() interface 2026-07-07 09:09:57 +02:00
2 changed files with 64 additions and 12 deletions
+49 -11
View File
@@ -19,6 +19,7 @@ from napalm_device_types.models import (
NetworkTargetDict,
PackageDict,
SnapshotDict,
StorageTargetDict,
StorageVolumeDict,
VMConfigDict,
VMDict,
@@ -548,25 +549,35 @@ class HypervisorDriver(DeviceTypeDriver):
self,
name: str,
*,
template: str,
image_url: str,
cpu: int,
memory: int,
nics: List[NICConfigDict],
cloud_init_config: Dict[str, Any],
image_checksum: str | None = None,
ssh_public_keys: List[str] | None = None,
disk_resize_gb: int | None = None,
storage: str | None = None,
download_timeout: int = 300,
timeout: int = 180,
) -> VMProvisionResultDict:
"""
Create a new virtual machine from a Cloud-Init template.
Create a new virtual machine from a cloud image via Cloud-Init.
Clones a pre-existing VM template, configures virtual network interfaces,
and injects Cloud-Init configuration via a storage snippet or similar
mechanism. The resulting VM is left in a running state.
Downloads the cloud image (qcow2/raw) directly on the hypervisor if not
already cached there, creates a new VM shell, imports the image as its
root disk, configures virtual network interfaces, and injects Cloud-Init
configuration via a storage snippet or similar mechanism. The resulting
VM is left in a running state.
Implementations should cache downloaded images by URL/filename on the
hypervisor so repeated provisioning from the same image does not
re-download it every time.
Args:
name (string) - new VM display name
template (string) - hypervisor-internal ID/name of the template VM to clone
image_url (string) - URL of the cloud image to download and use as
the VM's root disk (e.g. an official Debian/Ubuntu cloud image).
cpu (int) - number of virtual CPUs to assign
memory (int) - RAM to assign in megabytes
nics (list[NICConfigDict]) - list of network interface configurations.
@@ -575,20 +586,29 @@ class HypervisorDriver(DeviceTypeDriver):
and dhcp flag.
cloud_init_config (dict) - user-data dict (will be rendered to YAML).
Should include hostname, bootstrap_token, runcmd, and any custom config.
image_checksum (string | None) - expected checksum of the downloaded
image (e.g. "sha256:<hex>"). If given, verified after download;
mismatch raises RuntimeError. If None, no verification is performed.
ssh_public_keys (list[str] | None) - SSH public keys to inject into guest.
If None or empty, no SSH key injection is performed.
disk_resize_gb (int | None) - resize root disk to this size in GB.
If None, disk remains template size. Default None.
timeout (int) - maximum seconds to wait for provisioning completion
(clone, config, start). Default 180.
If None, disk remains the downloaded image's native size. Default None.
storage (string | None) - name of the storage pool to place the root
disk on (a name returned by ``get_image_storages()``). If None,
the driver auto-detects the first enabled, node-available storage
whose content includes "images".
download_timeout (int) - maximum seconds to wait for the image download
(skipped entirely if already cached on the hypervisor). Default 300.
timeout (int) - maximum seconds to wait for the remaining provisioning
steps (VM creation, disk import, config, start). Default 180.
Returns:
VMProvisionResultDict - ``{"vmid": str, "name": str, "node": str}``
vmid is the hypervisor-internal VM ID as a string (numeric for Proxmox).
Raises:
RuntimeError - if provisioning fails (storage unavailable, invalid
config, timeout, etc.)
RuntimeError - if provisioning fails (download failure, checksum
mismatch, storage unavailable, invalid config, timeout, etc.)
"""
raise NotImplementedError
@@ -674,3 +694,21 @@ class HypervisorDriver(DeviceTypeDriver):
per-kind rules).
"""
raise NotImplementedError
def get_image_storages(self) -> List[StorageTargetDict]:
"""
List the storage pools a new VM's root disk may be placed on, scoped to
the specific node the VM will be created on.
Returns only storages that are actually usable for this purpose right
now: content includes "images", administratively enabled, and — for
hypervisors where storage can be restricted to a subset of cluster
nodes — available on this node specifically. A storage configured
cluster-wide but restricted to other nodes must not appear here, since
passing its name to ``create_vm_from_cloud_init(storage=...)`` would fail.
Returns:
List[StorageTargetDict] - each entry's ``name`` is directly usable
as ``create_vm_from_cloud_init``'s ``storage`` argument.
"""
raise NotImplementedError
+15 -1
View File
@@ -741,9 +741,23 @@ class NetworkTargetDict(TypedDict):
- OVS bridge: always vlan_aware (OVS bridges tag per-port regardless of a
dedicated "VLAN aware" setting).
- SDN vnet: never vlan_aware — the VLAN is already fixed by the vnet's zone/tag,
so a NIC attached to it must not also carry a ``vlan_tag``.
so a NIC attached to it must not also carry a ``vlan_tag``. That fixed VLAN
is surfaced via ``fixed_vlan_tag`` instead, for display purposes.
"""
name: str # Bridge or vnet name, usable directly as NICConfigDict.bridge
kind: str # "bridge" or "vnet"
vlan_aware: bool # True if a NICConfigDict.vlan_tag may be set on top of this target
fixed_vlan_tag: NotRequired[int | None] # vnet only: the VLAN ID already baked into it
class StorageTargetDict(TypedDict):
"""A selectable storage pool for a new VM's root disk (``create_vm_from_cloud_init``'s
``storage`` argument), scoped to the specific node the VM will be created on —
a storage restricted to other cluster nodes must not appear here.
"""
name: str # Storage pool name, usable directly as create_vm_from_cloud_init(storage=...)
type: str # Backend type: "dir", "lvmthin", "zfspool", "nfs", etc.
total_gb: float # Total capacity in gigabytes
available_gb: float # Free capacity in gigabytes