Skip to content

Commit de845cd

Browse files
authored
Merge pull request #242 from aserdean/fixup-multi-networks
Make multi-network tests self-contained by auto-creating the secondary NAD
2 parents 4670eca + 0fbbbe9 commit de845cd

4 files changed

Lines changed: 117 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ kubeconfig_infra: (29)
165165
| measure_power | Measure Power Usage |
166166
| validate_offload | Verify OvS Offload |
167167
20a. "test_cases" - (Optional) Restrict a plugin to run only for the specified test cases. Uses the same format as the top-level `test_cases` field. By default, the plugin runs for every test case.
168-
21. "secondary_network_nad" - (Optional) - The name of the secondary network for multi-homing and multi-networkpolicies tests. For tests except 27-31, the primary network will be used if unspecified (the default which is None). For mandatory tests 27-31 it defaults to "tft-secondary" if not set. Can be overridden per-node using the server/client level `secondary_network_nad` fields.
168+
21. "secondary_network_nad" - (Optional) - The name of the secondary network for multi-homing and multi-networkpolicies tests. For tests except 27-31, the primary network will be used if unspecified (the default which is None). For mandatory tests 27-31 it defaults to "tft-secondary" if not set. Can be overridden per-node using the server/client level `secondary_network_nad` fields. The framework automatically creates and cleans up the NAD when these test cases are selected or when SRIOV nodes reference a secondary NAD. Subnets, MTU, and topology default to `10.193.0.0/16/26`, `1500`, and `layer3`, overridable via `TFT_SECONDARY_NAD_SUBNETS`, `TFT_SECONDARY_NAD_MTU`, and `TFT_SECONDARY_NAD_TOPOLOGY`.
169169
22. "resource_name" - (Optional) - The resource name for tests that require resource limit and requests to be set. This field is optional and will default to None if not set, but if secondary network nad is defined, traffic flow test
170170
tool will try to autopopulate resource_name based on the secondary+network_nad provided.
171171
23. "cpu_request" - (Optional) CPU request for server and client pods (e.g. "10m", "500m"). No CPU request is set if omitted.

manifests/secondary-nad.yaml.j2

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: "k8s.cni.cncf.io/v1"
2+
kind: NetworkAttachmentDefinition
3+
metadata:
4+
name: {{ nad_name }}
5+
namespace: {{ name_space }}
6+
labels:
7+
tft-tests: "secondary-nad"
8+
spec:
9+
config: '{
10+
"cniVersion": "0.4.0",
11+
"name": {{ nad_name }},
12+
"netAttachDefName": {{ net_attach_def_name }},
13+
"Role": "secondary",
14+
"topology": {{ topology }},
15+
"subnets": {{ subnets }},
16+
"mtu": {{ mtu }},{% if has_resource_name %}
17+
"resourceName": {{ resource_name }},{% endif %}
18+
"type": "ovn-k8s-cni-overlay",
19+
"logFile": "/var/log/ovn-kubernetes/flowtest.log",
20+
"logLevel": "5",
21+
"logfile-maxsize": 100,
22+
"logfile-maxbackups": 5,
23+
"logfile-maxage": 5
24+
}'

tftbase.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ def get_tft_external_server_string() -> Optional[str]:
184184
ENV_TFT_UDN_PRIMARY_CIDR = "TFT_UDN_PRIMARY_CIDR"
185185
ENV_TFT_UDN_SECONDARY_CIDR = "TFT_UDN_SECONDARY_CIDR"
186186

187+
ENV_TFT_SECONDARY_NAD_SUBNETS = "TFT_SECONDARY_NAD_SUBNETS"
188+
ENV_TFT_SECONDARY_NAD_MTU = "TFT_SECONDARY_NAD_MTU"
189+
ENV_TFT_SECONDARY_NAD_TOPOLOGY = "TFT_SECONDARY_NAD_TOPOLOGY"
190+
187191

188192
@functools.cache
189193
def get_udn_primary_cidr() -> str:
@@ -199,6 +203,27 @@ def get_udn_secondary_cidr() -> str:
199203
return s
200204

201205

206+
@functools.cache
207+
def get_secondary_nad_subnets() -> str:
208+
s = get_environ(ENV_TFT_SECONDARY_NAD_SUBNETS) or "10.193.0.0/16/26"
209+
logger.info(f"env: {ENV_TFT_SECONDARY_NAD_SUBNETS}={shlex.quote(s)}")
210+
return s
211+
212+
213+
@functools.cache
214+
def get_secondary_nad_mtu() -> int:
215+
s = get_environ(ENV_TFT_SECONDARY_NAD_MTU) or "1500"
216+
logger.info(f"env: {ENV_TFT_SECONDARY_NAD_MTU}={shlex.quote(s)}")
217+
return int(s)
218+
219+
220+
@functools.cache
221+
def get_secondary_nad_topology() -> str:
222+
s = get_environ(ENV_TFT_SECONDARY_NAD_TOPOLOGY) or "layer3"
223+
logger.info(f"env: {ENV_TFT_SECONDARY_NAD_TOPOLOGY}={shlex.quote(s)}")
224+
return s
225+
226+
202227
T = typing.TypeVar("T")
203228

204229

trafficFlowTests.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,70 @@ def _setup_udn(self, cfg_descr: ConfigDescriptor) -> None:
136136
self._configure_namespace(cfg_descr, namespace=udn_ns)
137137
self._udn_setup_done = True
138138

139+
def _setup_secondary_nad(self, cfg_descr: ConfigDescriptor) -> None:
140+
tft = cfg_descr.get_tft()
141+
if not any(
142+
tc.info.connection_mode
143+
in (
144+
tftbase.ConnectionMode.MULTI_HOME,
145+
tftbase.ConnectionMode.MNP_2ND_ALLOW,
146+
tftbase.ConnectionMode.MNP_2ND_DENY,
147+
tftbase.ConnectionMode.MNP_PRIMARY_DENY,
148+
)
149+
for tc in tft.test_cases
150+
) and not any(c.secondary_network_nad is not None for c in tft.connections):
151+
return
152+
153+
namespace = tft.namespace
154+
client = cfg_descr.tc.client_tenant
155+
nad = cfg_descr.get_tft().connections[0].effective_secondary_network_nad
156+
nad_name = nad.split("/")[-1]
157+
158+
existing = client.oc_get(
159+
f"network-attachment-definition/{nad_name}",
160+
namespace=namespace,
161+
may_fail=True,
162+
)
163+
if existing is not None:
164+
return
165+
166+
logger.info(f"Creating secondary NAD {nad} in namespace {namespace}")
167+
168+
resource_names = {c.resource_name for c in tft.connections}
169+
resource_name = (
170+
resource_names.pop()
171+
if len(resource_names) == 1 and None not in resource_names
172+
else None
173+
)
174+
175+
_j = json.dumps
176+
in_template = tftbase.get_manifest("secondary-nad.yaml.j2")
177+
out_yaml = tftbase.get_manifest_renderpath("secondary-nad.yaml")
178+
kjinja2.render_file(
179+
in_template,
180+
{
181+
"nad_name": _j(nad_name),
182+
"name_space": _j(namespace),
183+
"net_attach_def_name": _j(nad),
184+
"subnets": _j(tftbase.get_secondary_nad_subnets()),
185+
"mtu": tftbase.get_secondary_nad_mtu(),
186+
"topology": _j(tftbase.get_secondary_nad_topology()),
187+
"has_resource_name": resource_name is not None,
188+
"resource_name": _j(resource_name or ""),
189+
},
190+
out_file=out_yaml,
191+
)
192+
client.oc(f"apply -f {out_yaml}", die_on_error=True)
193+
194+
def _cleanup_secondary_nad(self, cfg_descr: ConfigDescriptor) -> None:
195+
namespace = cfg_descr.get_tft().namespace
196+
client = cfg_descr.tc.client_tenant
197+
client.oc(
198+
"delete network-attachment-definition -l tft-tests=secondary-nad",
199+
namespace=namespace,
200+
may_fail=True,
201+
)
202+
139203
def _cleanup_multi_network_policies(self, cfg_descr: ConfigDescriptor) -> None:
140204
namespace = cfg_descr.get_tft().namespace
141205
client = cfg_descr.tc.client_tenant
@@ -192,6 +256,8 @@ def _cleanup_previous_testspace(
192256
client.oc("delete pods -l tft-tests", namespace=namespace)
193257
client.oc("delete services -l tft-tests", namespace=namespace)
194258
self._cleanup_multi_network_policies(cfg_descr)
259+
if force_cleanup:
260+
self._cleanup_secondary_nad(cfg_descr)
195261

196262
if self._udn_setup_done:
197263
udn_ns = f"{namespace}-udn"
@@ -412,6 +478,7 @@ def test_run(
412478
ns_created = self._configure_namespace(cfg_descr)
413479
self._cleanup_stale_udn(cfg_descr)
414480
self._cleanup_previous_testspace(cfg_descr, force_cleanup=True)
481+
self._setup_secondary_nad(cfg_descr)
415482

416483
try:
417484
if test.pre_provision:

0 commit comments

Comments
 (0)