mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 09:40:20 +00:00
parent
a83504cb34
commit
b296fa2cbc
3 changed files with 67 additions and 8 deletions
1
changelog/62558.fixed
Normal file
1
changelog/62558.fixed
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fixed salt-cloud cloning a proxmox VM with a specified new vmid.
|
|
@ -676,10 +676,7 @@ def create(vm_):
|
||||||
|
|
||||||
ret["creation_data"] = data
|
ret["creation_data"] = data
|
||||||
name = vm_["name"] # hostname which we know
|
name = vm_["name"] # hostname which we know
|
||||||
if "clone" in vm_ and vm_["clone"] is True:
|
vmid = data["vmid"] # vmid which we have received
|
||||||
vmid = newid
|
|
||||||
else:
|
|
||||||
vmid = data["vmid"] # vmid which we have received
|
|
||||||
host = data["node"] # host which we have received
|
host = data["node"] # host which we have received
|
||||||
nodeType = data["technology"] # VM tech (Qemu / OpenVZ)
|
nodeType = data["technology"] # VM tech (Qemu / OpenVZ)
|
||||||
|
|
||||||
|
@ -1015,6 +1012,7 @@ def create_node(vm_, newid):
|
||||||
)
|
)
|
||||||
for prop in _get_properties("/nodes/{node}/qemu", "POST", static_props):
|
for prop in _get_properties("/nodes/{node}/qemu", "POST", static_props):
|
||||||
if prop in vm_: # if the property is set, use it for the VM request
|
if prop in vm_: # if the property is set, use it for the VM request
|
||||||
|
# If specified, vmid will override newid.
|
||||||
newnode[prop] = vm_[prop]
|
newnode[prop] = vm_[prop]
|
||||||
|
|
||||||
# The node is ready. Lets request it to be added
|
# The node is ready. Lets request it to be added
|
||||||
|
@ -1057,7 +1055,12 @@ def create_node(vm_, newid):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
node = query("post", "nodes/{}/{}".format(vmhost, vm_["technology"]), newnode)
|
node = query("post", "nodes/{}/{}".format(vmhost, vm_["technology"]), newnode)
|
||||||
return _parse_proxmox_upid(node, vm_)
|
result = _parse_proxmox_upid(node, vm_)
|
||||||
|
|
||||||
|
# When cloning, the upid contains the clone_from vmid instead of the new vmid
|
||||||
|
result["vmid"] = newnode["vmid"]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def show_instance(name, call=None):
|
def show_instance(name, call=None):
|
||||||
|
|
|
@ -150,7 +150,7 @@ class ProxmoxTest(TestCase, LoaderModuleMockMixin):
|
||||||
"nodes/myhost/qemu/123/clone",
|
"nodes/myhost/qemu/123/clone",
|
||||||
{"newid": ANY},
|
{"newid": ANY},
|
||||||
)
|
)
|
||||||
assert result == {}
|
assert result == {"vmid": ANY}
|
||||||
|
|
||||||
# CASE 2: host:ID notation
|
# CASE 2: host:ID notation
|
||||||
mock_query.reset_mock()
|
mock_query.reset_mock()
|
||||||
|
@ -161,7 +161,7 @@ class ProxmoxTest(TestCase, LoaderModuleMockMixin):
|
||||||
"nodes/otherhost/qemu/123/clone",
|
"nodes/otherhost/qemu/123/clone",
|
||||||
{"newid": ANY},
|
{"newid": ANY},
|
||||||
)
|
)
|
||||||
assert result == {}
|
assert result == {"vmid": ANY}
|
||||||
|
|
||||||
def test_clone_pool(self):
|
def test_clone_pool(self):
|
||||||
"""
|
"""
|
||||||
|
@ -186,7 +186,62 @@ class ProxmoxTest(TestCase, LoaderModuleMockMixin):
|
||||||
"nodes/myhost/qemu/123/clone",
|
"nodes/myhost/qemu/123/clone",
|
||||||
{"newid": ANY, "pool": "mypool"},
|
{"newid": ANY, "pool": "mypool"},
|
||||||
)
|
)
|
||||||
assert result == {}
|
assert result == {"vmid": ANY}
|
||||||
|
|
||||||
|
def test_clone_id(self):
|
||||||
|
"""
|
||||||
|
Test cloning a VM with a specified vmid.
|
||||||
|
"""
|
||||||
|
next_vmid = 101
|
||||||
|
explicit_vmid = 201
|
||||||
|
upid = "UPID:myhost:00123456:12345678:9ABCDEF0:qmclone:123:root@pam:"
|
||||||
|
|
||||||
|
def mock_query_response(conn_type, option, post_data=None):
|
||||||
|
if conn_type == "get" and option == "cluster/tasks":
|
||||||
|
return [{"upid": upid, "status": "OK"}]
|
||||||
|
if conn_type == "post" and option.endswith("/clone"):
|
||||||
|
return upid
|
||||||
|
return None
|
||||||
|
|
||||||
|
mock_wait_for_state = MagicMock(return_value=True)
|
||||||
|
with patch(
|
||||||
|
"salt.cloud.clouds.proxmox._get_properties",
|
||||||
|
MagicMock(return_value=["vmid"]),
|
||||||
|
), patch(
|
||||||
|
"salt.cloud.clouds.proxmox._get_next_vmid",
|
||||||
|
MagicMock(return_value=next_vmid),
|
||||||
|
), patch(
|
||||||
|
"salt.cloud.clouds.proxmox.start", MagicMock(return_value=True)
|
||||||
|
), patch(
|
||||||
|
"salt.cloud.clouds.proxmox.wait_for_state", mock_wait_for_state
|
||||||
|
), patch(
|
||||||
|
"salt.cloud.clouds.proxmox.query", side_effect=mock_query_response
|
||||||
|
):
|
||||||
|
vm_ = {
|
||||||
|
"profile": "my_proxmox",
|
||||||
|
"driver": "proxmox",
|
||||||
|
"technology": "qemu",
|
||||||
|
"name": "new2",
|
||||||
|
"host": "myhost",
|
||||||
|
"clone": True,
|
||||||
|
"clone_from": 123,
|
||||||
|
"ip_address": "10.10.10.10",
|
||||||
|
}
|
||||||
|
|
||||||
|
# CASE 1: No vmid specified in profile (previous behavior)
|
||||||
|
proxmox.create(vm_)
|
||||||
|
mock_wait_for_state.assert_called_with(
|
||||||
|
next_vmid,
|
||||||
|
"running",
|
||||||
|
)
|
||||||
|
|
||||||
|
# CASE 2: vmid specified in profile
|
||||||
|
vm_["vmid"] = explicit_vmid
|
||||||
|
proxmox.create(vm_)
|
||||||
|
mock_wait_for_state.assert_called_with(
|
||||||
|
explicit_vmid,
|
||||||
|
"running",
|
||||||
|
)
|
||||||
|
|
||||||
def test_find_agent_ips(self):
|
def test_find_agent_ips(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Add table
Reference in a new issue