1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-11 12:46:49 +00:00

feat(instances): a VM's clone form in device cards, with fixes to what it clones

Settings > Clone was a horizontal form with unlabelled checkboxes. The
owner chose this layout from three rendered options: the clone's name
on top, a "Network" card with a new MAC address per NIC, a "Storage"
card with a new volume name per disk, then the optional title and
description and a footer with Clone.

Codex reviewed cloning end to end; these are fixed:

- Every NIC of the clone gets a new random MAC when the form opens.
  Only the first did, so a VM with two NICs gave its clone the second
  NIC's MAC. Guess MAC is offered for the first NIC only: a name's DHCP
  host entry holds one address.
- A VM without a NIC can be cloned: the first NIC's MAC was required.
- The disk name script uses the persistent disks, as the form does; a
  disk added pending the next start kept the source's volume name.
- A running or paused VM is not cloned while a copied disk changes at
  the next start: the backup copies the running disk, so the clone
  would get the old contents under the new definition.
- A derived volume name that does not start with the source's name now
  starts with the clone's name and the disk's device, so a second clone
  or a second disk does not take the same name.
- Guess for the clone name says when the DHCP file has no free name; it
  stopped with a script error.
- The qcow2 metadata preallocation box shows only for a shut-off VM: a
  live clone's backup ignores it.

Other users no longer get hidden MAC and disk inputs or the scripts that
filled them: the server derives those values and ignored the posted ones.
This commit is contained in:
catborise 2026-10-30 13:32:28 +03:00
parent 301b73155d
commit 400ba1614f
8 changed files with 164 additions and 96 deletions

View file

@ -358,17 +358,20 @@ def get_random_mac_address():
return mac
def get_clone_disk_name(disk, prefix, clone_name=""):
def get_clone_disk_name(disk, prefix, clone_name):
"""A volume name for the clone's copy of disk: the clone's name in place of
the source's (prefix), else before the disk's device and name, so two disks
of one clone do not get the same name."""
if not disk["image"]:
return None
if disk["image"].startswith(prefix) and clone_name:
if disk["image"].startswith(prefix):
suffix = disk["image"][len(prefix) :]
image = f"{clone_name}{suffix}"
elif "." in disk["image"] and len(disk["image"].rsplit(".", 1)[1]) <= 7:
name, suffix = disk["image"].rsplit(".", 1)
image = f"{name}-clone.{suffix}"
image = f"{clone_name}-{disk['dev']}-{name}.{suffix}"
else:
image = f"{disk['image']}-clone"
image = f"{clone_name}-{disk['dev']}-{disk['image']}"
# Derived names go into volume XML and paths: keep them to a safe charset.
image = re.sub(r"[^A-Za-z0-9_.+-]+", "-", image).lstrip("_.+-")
return image or None