Skip to content

Commit 499d775

Browse files
authored
lock sensord restart (#594)
1 parent aa32bef commit 499d775

File tree

2 files changed

+70
-11
lines changed

2 files changed

+70
-11
lines changed

sonic_platform_base/module_base.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class ModuleBase(device_base.DeviceBase):
2727
# Device type definition. Note, this is a constant.
2828
DEVICE_TYPE = "module"
2929
PCI_OPERATION_LOCK_FILE_PATH = "/var/lock/{}_pci.lock"
30+
SENSORD_OPERATION_LOCK_FILE_PATH = "/var/lock/sensord.lock"
3031

3132
# Possible card types for modular chassis
3233
MODULE_TYPE_SUPERVISOR = "SUPERVISOR"
@@ -96,16 +97,29 @@ def __init__(self):
9697
self._asic_list = []
9798

9899
@contextlib.contextmanager
99-
def _pci_operation_lock(self):
100-
"""File-based lock for PCI operations using flock"""
101-
lock_file_path = self.PCI_OPERATION_LOCK_FILE_PATH.format(self.get_name())
100+
def _file_operation_lock(self, lock_file_path):
101+
"""Common file-based lock for operations using flock"""
102102
with open(lock_file_path, 'w') as f:
103103
try:
104104
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
105105
yield
106106
finally:
107107
fcntl.flock(f.fileno(), fcntl.LOCK_UN)
108108

109+
@contextlib.contextmanager
110+
def _pci_operation_lock(self):
111+
"""File-based lock for PCI operations using flock"""
112+
lock_file_path = self.PCI_OPERATION_LOCK_FILE_PATH.format(self.get_name())
113+
with self._file_operation_lock(lock_file_path):
114+
yield
115+
116+
@contextlib.contextmanager
117+
def _sensord_operation_lock(self):
118+
"""File-based lock for sensord operations using flock"""
119+
lock_file_path = self.SENSORD_OPERATION_LOCK_FILE_PATH
120+
with self._file_operation_lock(lock_file_path):
121+
yield
122+
109123
def get_base_mac(self):
110124
"""
111125
Retrieves the base MAC address for the module
@@ -791,8 +805,9 @@ def handle_sensor_removal(self):
791805

792806
shutil.copy2(source_file, target_file)
793807

794-
# Restart sensord
795-
os.system("service sensord restart")
808+
# Restart sensord with lock
809+
with self._sensord_operation_lock():
810+
os.system("service sensord restart")
796811

797812
return True
798813
except Exception as e:
@@ -818,8 +833,9 @@ def handle_sensor_addition(self):
818833
# Remove the file
819834
os.remove(target_file)
820835

821-
# Restart sensord
822-
os.system("service sensord restart")
836+
# Restart sensord with lock
837+
with self._sensord_operation_lock():
838+
os.system("service sensord restart")
823839

824840
return True
825841
except Exception as e:

tests/module_base_test.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,23 @@ def test_pci_entry_state_db(self):
8787
mock_connector.hset.side_effect = Exception("DB Error")
8888
module.pci_entry_state_db("0000:00:00.0", "detaching")
8989

90+
def test_file_operation_lock(self):
91+
module = ModuleBase()
92+
mock_file = MockFile()
93+
94+
with patch('builtins.open', return_value=mock_file) as mock_file_open, \
95+
patch('fcntl.flock') as mock_flock, \
96+
patch('os.makedirs') as mock_makedirs:
97+
98+
with module._file_operation_lock("/var/lock/test.lock"):
99+
mock_flock.assert_called_with(123, fcntl.LOCK_EX)
100+
101+
mock_flock.assert_has_calls([
102+
call(123, fcntl.LOCK_EX),
103+
call(123, fcntl.LOCK_UN)
104+
])
105+
assert mock_file.fileno_called
106+
90107
def test_pci_operation_lock(self):
91108
module = ModuleBase()
92109
mock_file = MockFile()
@@ -105,6 +122,24 @@ def test_pci_operation_lock(self):
105122
])
106123
assert mock_file.fileno_called
107124

125+
def test_sensord_operation_lock(self):
126+
module = ModuleBase()
127+
mock_file = MockFile()
128+
129+
with patch('builtins.open', return_value=mock_file) as mock_file_open, \
130+
patch('fcntl.flock') as mock_flock, \
131+
patch.object(module, 'get_name', return_value="DPU0"), \
132+
patch('os.makedirs') as mock_makedirs:
133+
134+
with module._sensord_operation_lock():
135+
mock_flock.assert_called_with(123, fcntl.LOCK_EX)
136+
137+
mock_flock.assert_has_calls([
138+
call(123, fcntl.LOCK_EX),
139+
call(123, fcntl.LOCK_UN)
140+
])
141+
assert mock_file.fileno_called
142+
108143
def test_handle_pci_removal(self):
109144
module = ModuleBase()
110145

@@ -141,19 +176,23 @@ def test_handle_sensor_removal(self):
141176
with patch.object(module, 'get_name', return_value="DPU0"), \
142177
patch('os.path.exists', return_value=True), \
143178
patch('shutil.copy2') as mock_copy, \
144-
patch('os.system') as mock_system:
179+
patch('os.system') as mock_system, \
180+
patch.object(module, '_sensord_operation_lock') as mock_lock:
145181
assert module.handle_sensor_removal() is True
146182
mock_copy.assert_called_once_with("/usr/share/sonic/platform/module_sensors_ignore_conf/ignore_sensors_DPU0.conf",
147183
"/etc/sensors.d/ignore_sensors_DPU0.conf")
148184
mock_system.assert_called_once_with("service sensord restart")
185+
mock_lock.assert_called_once()
149186

150187
with patch.object(module, 'get_name', return_value="DPU0"), \
151188
patch('os.path.exists', return_value=False), \
152189
patch('shutil.copy2') as mock_copy, \
153-
patch('os.system') as mock_system:
190+
patch('os.system') as mock_system, \
191+
patch.object(module, '_sensord_operation_lock') as mock_lock:
154192
assert module.handle_sensor_removal() is True
155193
mock_copy.assert_not_called()
156194
mock_system.assert_not_called()
195+
mock_lock.assert_not_called()
157196

158197
with patch.object(module, 'get_name', return_value="DPU0"), \
159198
patch('os.path.exists', return_value=True), \
@@ -166,18 +205,22 @@ def test_handle_sensor_addition(self):
166205
with patch.object(module, 'get_name', return_value="DPU0"), \
167206
patch('os.path.exists', return_value=True), \
168207
patch('os.remove') as mock_remove, \
169-
patch('os.system') as mock_system:
208+
patch('os.system') as mock_system, \
209+
patch.object(module, '_sensord_operation_lock') as mock_lock:
170210
assert module.handle_sensor_addition() is True
171211
mock_remove.assert_called_once_with("/etc/sensors.d/ignore_sensors_DPU0.conf")
172212
mock_system.assert_called_once_with("service sensord restart")
213+
mock_lock.assert_called_once()
173214

174215
with patch.object(module, 'get_name', return_value="DPU0"), \
175216
patch('os.path.exists', return_value=False), \
176217
patch('os.remove') as mock_remove, \
177-
patch('os.system') as mock_system:
218+
patch('os.system') as mock_system, \
219+
patch.object(module, '_sensord_operation_lock') as mock_lock:
178220
assert module.handle_sensor_addition() is True
179221
mock_remove.assert_not_called()
180222
mock_system.assert_not_called()
223+
mock_lock.assert_not_called()
181224

182225
with patch.object(module, 'get_name', return_value="DPU0"), \
183226
patch('os.path.exists', return_value=True), \

0 commit comments

Comments
 (0)