Skip to content

Commit e5427ec

Browse files
Add horizon neutron ports fix (#286)
Signed-off-by: ricolin <rlin@vexxhost.com> Co-authored-by: ricolin <rlin@vexxhost.com>
1 parent 632c15b commit e5427ec

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
From c2d951d7d557e07b725a7400f9bdb36bc229d262 Mon Sep 17 00:00:00 2001
2+
From: Dong Ma <winterma.dong@gmail.com>
3+
Date: Wed, 4 Feb 2026 13:42:35 +0800
4+
Subject: [PATCH] fix(api): Avoid RecursionError when deepcopy Port apidict
5+
6+
When the apidict passed to Port.__init__ is an openstacksdk Resource
7+
object, calling copy.deepcopy() on it can trigger a RecursionError.
8+
This happens because openstacksdk CloudRegion.__getattr__ method
9+
can cause infinite recursion during deepcopy operations.
10+
11+
This fix converts the apidict to a plain dict using to_dict() before
12+
deepcopy if the method is available, avoiding the recursion issue.
13+
14+
Change-Id: Ia0de61ae6461c06158b285923d1abab373b4b792
15+
Signed-off-by: Dong Ma <winterma.dong@gmail.com>
16+
---
17+
openstack_dashboard/api/neutron.py | 8 +++++++-
18+
1 file changed, 7 insertions(+), 1 deletion(-)
19+
20+
diff --git a/openstack_dashboard/api/neutron.py b/openstack_dashboard/api/neutron.py
21+
index bce0c20d3..423f3ac18 100644
22+
--- a/openstack_dashboard/api/neutron.py
23+
+++ b/openstack_dashboard/api/neutron.py
24+
@@ -203,7 +203,13 @@ class Port(NeutronAPIDictWrapper):
25+
ON_STATE if apidict['mac_learning_enabled'] else OFF_STATE
26+
pairs = apidict.get('allowed_address_pairs')
27+
if pairs:
28+
- apidict = copy.deepcopy(apidict)
29+
+ # Convert to dict first if possible to avoid RecursionError
30+
+ # when deepcopy encounters openstacksdk objects with custom
31+
+ # __getattr__ methods. to_dict() already returns a new dict.
32+
+ if hasattr(apidict, 'to_dict'):
33+
+ apidict = apidict.to_dict()
34+
+ else:
35+
+ apidict = copy.deepcopy(apidict)
36+
wrapped_pairs = [PortAllowedAddressPair(pair) for pair in pairs]
37+
apidict['allowed_address_pairs'] = wrapped_pairs
38+
super().__init__(apidict)
39+
--
40+
2.25.1
41+

0 commit comments

Comments
 (0)