1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-10 20:26:48 +00:00

fix(instances): a clone's name is at most 64 characters, as a new VM's

The name's length was not checked: libvirt defined a clone of a name
longer than the panel's records hold (120), and the job failed to record
it, leaving a VM the panel did not list. The form and the job take 64,
as for a new VM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kk4h2TcUiaWmU5MUszYSea
This commit is contained in:
catborise 2026-11-07 23:43:36 +03:00
parent c18e89ae0f
commit 41ef48f2e0
7 changed files with 224 additions and 205 deletions

View file

@ -197,6 +197,9 @@ def clone_data(user, instance, fields):
quota=utils.quota_message(quota_msg), clone_name=data["name"])
if check_instance:
raise util.OperationError(_("Instance '%(clone_name)s' already exists!"), clone_name=data["name"])
if len(data["name"]) > 64: # as a new VM's: the panel's records hold 120
raise util.OperationError(_("Instance name '%(clone_name)s' is longer than 64 characters"),
clone_name=data["name"])
if not re.match(r"^[a-zA-Z0-9-]+$", data["name"]):
raise util.OperationError(_("Instance name '%(clone_name)s' contains invalid characters!"),
clone_name=data["name"])

View file

@ -775,7 +775,7 @@
<label class="form-label" for="clone_name">{% trans "Clone name" %}</label>
<div class="row g-2">
<div class="col-12 col-sm">
<input class="form-control" id="clone_name" name="name" type="text" value="{{ instance.name }}-clone" aria-describedby="clone-name-help"
<input class="form-control" id="clone_name" name="name" type="text" maxlength="64" value="{{ instance.name }}-clone" aria-describedby="clone-name-help"
data-source="{{ instance.name }}" data-guess-url="{% url 'instances:guess_clone_name' %}"
data-guess-mac-url="{% url 'instances:guess_mac_address' '__name__' %}">
</div>

View file

@ -334,6 +334,12 @@ class LiveCloneJobTestCase(TransactionTestCase):
self.assertTrue(intent["live"])
op.delete()
def test_a_name_longer_than_a_new_vm_s_is_refused(self):
name = "c" * 65
with self.assertRaisesMessage(OperationError, "is longer than 64 characters"):
CloneInstance().plan(self.admin, {"instance": self.source.pk, "fields": {
"name": name, "disk-vda": "copy.qcow2", "clone-net-mac-0": "52:54:00:00:00:01"}})
def test_another_state_is_refused(self):
self.proxy.get_status.return_value = 4 # shutting down
with self.assertRaisesMessage(OperationError, "The VM must be running, paused or shut off to be cloned"):