Skip to content

Commit badfa40

Browse files
committed
adding pick mode
1 parent 26edfbf commit badfa40

1 file changed

Lines changed: 132 additions & 0 deletions

File tree

tests/test_vmi_network_filter.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,138 @@ def test_run_rollback_passes_correct_pid_iface_and_rules_to_clean(
579579
self.assertEqual(clean_args[6], ["out_rule"]) # output_rules from apply
580580

581581

582+
class TestVmiNetworkFilterNetworkMode(unittest.TestCase):
583+
584+
def setUp(self):
585+
self.mock_kubecli = MagicMock()
586+
self.mock_kubernetes = MagicMock()
587+
self.mock_kubecli.get_lib_kubernetes.return_value = self.mock_kubernetes
588+
589+
self.mock_kubernetes.list_pods.return_value = ["virt-launcher-virt-server-3-abc12"]
590+
compute = _make_container("compute", ready=True, container_id="containerd://deadbeef")
591+
mock_pod_info = MagicMock()
592+
mock_pod_info.containers = [compute]
593+
self.mock_kubernetes.get_pod_info.return_value = mock_pod_info
594+
self.mock_kubernetes.get_pod_pids.return_value = ["100", "101", "102"]
595+
596+
def _vmi_with_mode(self, mode: str) -> dict:
597+
binding = {mode: {}}
598+
return {
599+
"status": {"nodeName": "worker-1"},
600+
"spec": {"domain": {"devices": {"interfaces": [{"name": "default", **binding}]}}},
601+
}
602+
603+
def _run_success(self, vmi: dict, **config_overrides):
604+
config = _make_config(**config_overrides)
605+
module = VmiNetworkFilterModule(config, self.mock_kubecli)
606+
self.mock_kubernetes.get_vmi.return_value = vmi
607+
with patch(f"{MODULE}.deploy_network_chaos_ng_pod"), \
608+
patch(f"{MODULE}.find_virt_launcher_netns_pid", return_value="101"), \
609+
patch(f"{MODULE}.get_vmi_tap_interface", return_value="tap0"), \
610+
patch(f"{MODULE}.get_vmi_masquerade_interface", return_value="eth0"), \
611+
patch(f"{MODULE}.apply_tc_vmi_chaos", return_value=([], [])) as mock_apply, \
612+
patch(f"{MODULE}.clean_tc_vmi_chaos"), \
613+
patch(f"{MODULE}.time.sleep"), \
614+
patch(f"{MODULE}.log_info"):
615+
module.run("virt-density-udn-3/virt-server-3")
616+
return mock_apply
617+
618+
# ------------------------------------------------------------------ mode detection
619+
620+
def test_bridge_mode_uses_tap_interface(self):
621+
with patch(f"{MODULE}.get_vmi_tap_interface", return_value="tap0") as mock_tap, \
622+
patch(f"{MODULE}.get_vmi_masquerade_interface") as mock_masq, \
623+
patch(f"{MODULE}.deploy_network_chaos_ng_pod"), \
624+
patch(f"{MODULE}.find_virt_launcher_netns_pid", return_value="101"), \
625+
patch(f"{MODULE}.apply_tc_vmi_chaos", return_value=([], [])), \
626+
patch(f"{MODULE}.clean_tc_vmi_chaos"), \
627+
patch(f"{MODULE}.time.sleep"), \
628+
patch(f"{MODULE}.log_info"):
629+
config = _make_config()
630+
module = VmiNetworkFilterModule(config, self.mock_kubecli)
631+
self.mock_kubernetes.get_vmi.return_value = self._vmi_with_mode("bridge")
632+
module.run("virt-density-udn-3/virt-server-3")
633+
634+
mock_tap.assert_called_once()
635+
mock_masq.assert_not_called()
636+
637+
def test_masquerade_mode_uses_default_interface(self):
638+
with patch(f"{MODULE}.get_vmi_tap_interface") as mock_tap, \
639+
patch(f"{MODULE}.get_vmi_masquerade_interface", return_value="eth0") as mock_masq, \
640+
patch(f"{MODULE}.deploy_network_chaos_ng_pod"), \
641+
patch(f"{MODULE}.find_virt_launcher_netns_pid", return_value="101"), \
642+
patch(f"{MODULE}.apply_tc_vmi_chaos", return_value=([], [])), \
643+
patch(f"{MODULE}.clean_tc_vmi_chaos"), \
644+
patch(f"{MODULE}.time.sleep"), \
645+
patch(f"{MODULE}.log_info"):
646+
config = _make_config()
647+
module = VmiNetworkFilterModule(config, self.mock_kubecli)
648+
self.mock_kubernetes.get_vmi.return_value = self._vmi_with_mode("masquerade")
649+
module.run("virt-density-udn-3/virt-server-3")
650+
651+
mock_masq.assert_called_once()
652+
mock_tap.assert_not_called()
653+
654+
def test_masquerade_mode_apply_called_with_eth0(self):
655+
mock_apply = self._run_success(self._vmi_with_mode("masquerade"))
656+
iface_arg = mock_apply.call_args[0][4]
657+
self.assertEqual(iface_arg, "eth0")
658+
659+
def test_bridge_mode_apply_called_with_tap0(self):
660+
mock_apply = self._run_success(self._vmi_with_mode("bridge"))
661+
iface_arg = mock_apply.call_args[0][4]
662+
self.assertEqual(iface_arg, "tap0")
663+
664+
def test_sriov_mode_raises(self):
665+
config = _make_config()
666+
module = VmiNetworkFilterModule(config, self.mock_kubecli)
667+
self.mock_kubernetes.get_vmi.return_value = self._vmi_with_mode("sriov")
668+
with patch(f"{MODULE}.deploy_network_chaos_ng_pod"), \
669+
patch(f"{MODULE}.log_info"):
670+
with self.assertRaises(Exception) as ctx:
671+
module.run("virt-density-udn-3/virt-server-3")
672+
self.assertIn("sriov", str(ctx.exception))
673+
self.assertIn("not supported", str(ctx.exception))
674+
675+
def test_macvtap_mode_raises(self):
676+
config = _make_config()
677+
module = VmiNetworkFilterModule(config, self.mock_kubecli)
678+
self.mock_kubernetes.get_vmi.return_value = self._vmi_with_mode("macvtap")
679+
with patch(f"{MODULE}.deploy_network_chaos_ng_pod"), \
680+
patch(f"{MODULE}.log_info"):
681+
with self.assertRaises(Exception) as ctx:
682+
module.run("virt-density-udn-3/virt-server-3")
683+
self.assertIn("macvtap", str(ctx.exception))
684+
self.assertIn("not supported", str(ctx.exception))
685+
686+
def test_explicit_interface_skips_mode_detection(self):
687+
"""If interfaces is set in config, neither tap nor masquerade detection is called."""
688+
with patch(f"{MODULE}.get_vmi_tap_interface") as mock_tap, \
689+
patch(f"{MODULE}.get_vmi_masquerade_interface") as mock_masq, \
690+
patch(f"{MODULE}.deploy_network_chaos_ng_pod"), \
691+
patch(f"{MODULE}.find_virt_launcher_netns_pid", return_value="101"), \
692+
patch(f"{MODULE}.apply_tc_vmi_chaos", return_value=([], [])) as mock_apply, \
693+
patch(f"{MODULE}.clean_tc_vmi_chaos"), \
694+
patch(f"{MODULE}.time.sleep"), \
695+
patch(f"{MODULE}.log_info"):
696+
config = _make_config(interfaces=["bond0"])
697+
module = VmiNetworkFilterModule(config, self.mock_kubecli)
698+
self.mock_kubernetes.get_vmi.return_value = self._vmi_with_mode("masquerade")
699+
module.run("virt-density-udn-3/virt-server-3")
700+
701+
mock_tap.assert_not_called()
702+
mock_masq.assert_not_called()
703+
iface_arg = mock_apply.call_args[0][4]
704+
self.assertEqual(iface_arg, "bond0")
705+
706+
def test_no_mode_in_spec_defaults_to_bridge(self):
707+
"""VMI with no binding in spec should be treated as bridge mode."""
708+
vmi = {"status": {"nodeName": "worker-1"}, "spec": {}}
709+
mock_apply = self._run_success(vmi)
710+
iface_arg = mock_apply.call_args[0][4]
711+
self.assertEqual(iface_arg, "tap0")
712+
713+
582714
class TestVmiNetworkFilterPortsProtocols(unittest.TestCase):
583715

584716
def setUp(self):

0 commit comments

Comments
 (0)