Enhance documentation and validation for VM lifecycle and network management; add tests for legacy cleanup and address validation.
This commit is contained in:
@@ -442,6 +442,80 @@ class FirewallManagerTests(unittest.TestCase):
|
||||
with self.assertRaises(CommandError):
|
||||
self.manager.cleanup_connections(self.vm)
|
||||
|
||||
def test_legacy_cleanup_outside_current_network_uses_only_recorded_ip(self):
|
||||
record = dict(id="vm-legacy", cpu=1, ram_mib=128, guest_ip="203.0.113.7",
|
||||
gateway="203.0.113.1", tap="tap-legacy", mac=self.vm.mac,
|
||||
socket="", config="", log="", status="stopped")
|
||||
for stored_network in (None, "203.0.113.0/24"):
|
||||
with self.subTest(network=stored_network):
|
||||
vm = VmRecord.from_dict({**record, **({"network": stored_network} if stored_network else {})})
|
||||
self.assertIsNone(vm.ports)
|
||||
self.runner.calls.clear()
|
||||
self.manager.cleanup_connections(vm)
|
||||
expected = [("ip", "-j", "-d", "link", "show")]
|
||||
expected.extend(("conntrack", command, "--family", "ipv4", field, "203.0.113.7")
|
||||
for field in ("--orig-src", "--orig-dst", "--reply-src", "--reply-dst")
|
||||
for command in ("--delete", "--list"))
|
||||
# No nft policy, publishing, or unrelated address/conntrack flush.
|
||||
self.assertEqual([args for args, _ in self.runner.calls], expected)
|
||||
|
||||
def test_cleanup_host_boundaries_use_stored_network_not_current_settings(self):
|
||||
cases = (
|
||||
("10.77.8.2", "10.77.0.0/16"),
|
||||
("100.64.3.4", "100.64.0.0/16"),
|
||||
("10.42.0.1", None), # Current gateway is not a cleanup constraint.
|
||||
("10.42.0.0", None), # Do not guess the old prefix from current settings.
|
||||
("10.42.0.255", None),
|
||||
("203.0.113.0", "203.0.0.0/16"),
|
||||
("203.0.113.255", "203.0.0.0/16"),
|
||||
("203.0.113.8", "203.0.113.8/31"),
|
||||
("203.0.113.9", "203.0.113.8/31"),
|
||||
("203.0.113.8", "203.0.113.8/32"),
|
||||
)
|
||||
for address, network in cases:
|
||||
with self.subTest(address=address, network=network):
|
||||
self.runner.calls.clear()
|
||||
self.manager.cleanup_connections(vm_record(guest_ip=address, network=network, ports=None))
|
||||
deletes = [args for args, _ in self.runner.calls if args[:2] == ("conntrack", "--delete")]
|
||||
self.assertEqual(len(deletes), 4)
|
||||
self.assertTrue(all(args[-1] == address for args in deletes))
|
||||
|
||||
def test_cleanup_rejects_invalid_or_non_host_persisted_addresses(self):
|
||||
cases = [(address, None) for address in (
|
||||
"not-an-ip", "203.0.113.999", "203.0.113.7/24", "2001:db8::7",
|
||||
"::ffff:203.0.113.7", None, True, 3405803783,
|
||||
"0.0.0.0", "127.0.0.1", "127.12.2.3", "169.254.1.2",
|
||||
"224.0.0.1", "239.255.255.255", "255.255.255.255",
|
||||
)]
|
||||
cases.extend((
|
||||
("203.0.113.0", "203.0.113.0/24"),
|
||||
("203.0.113.255", "203.0.113.0/24"),
|
||||
("203.0.113.7", "203.0.114.0/24"),
|
||||
("203.0.113.7", "not-a-network"),
|
||||
("203.0.113.7", ""),
|
||||
("203.0.113.7", "2001:db8::/64"),
|
||||
))
|
||||
for address, network in cases:
|
||||
with self.subTest(address=address, network=network):
|
||||
self.runner.calls.clear()
|
||||
with self.assertRaises(ValidationError):
|
||||
self.manager.cleanup_connections(vm_record(guest_ip=address, network=network, ports=None))
|
||||
self.assertEqual([args for args, _ in self.runner.calls], [("ip", "-j", "-d", "link", "show")])
|
||||
|
||||
def test_legacy_public_cleanup_still_requires_tap_absence(self):
|
||||
self.runner.links = [{"ifname": "tap-legacy"}]
|
||||
vm = vm_record(tap="tap-legacy", guest_ip="203.0.113.7", ports=None)
|
||||
with self.assertRaisesRegex(UvmError, "still exists"):
|
||||
self.manager.cleanup_connections(vm)
|
||||
self.assertFalse(any(args[0] == "conntrack" for args, _ in self.runner.calls))
|
||||
|
||||
def test_cleanup_compatibility_does_not_allow_a_public_managed_policy(self):
|
||||
vm = vm_record(guest_ip="203.0.113.7", network="203.0.113.0/24", ports=())
|
||||
with self.assertRaisesRegex(ValidationError, "private guest IP"):
|
||||
self.manager.apply(vm)
|
||||
self.assertEqual(self.runner.calls, [])
|
||||
self.manager.cleanup_connections(vm)
|
||||
|
||||
def test_availability_checks_kernel_and_full_policy_without_committing(self):
|
||||
self.manager.check_available()
|
||||
self.assertEqual(self.runner.tables, {})
|
||||
|
||||
Reference in New Issue
Block a user