@@ -158,3 +158,126 @@ def get_os_release_data():
158158 os_release_data_dict [param ] = param_val
159159
160160 return os_release_data_dict
161+
162+
163+ def get_numastat ():
164+ numastat_p = subprocess .Popen (
165+ ["numastat" , "-m" ], stdout = subprocess .PIPE , stderr = subprocess .PIPE
166+ )
167+ (numastat_data , err ) = numastat_p .communicate ()
168+ numastat_data = numastat_data .decode ("utf-8" ).split ("\n " )
169+
170+ numastat_dict = {}
171+ headers = []
172+ found_headers = False
173+
174+ for line in numastat_data :
175+ line = line .strip ()
176+ if not line :
177+ continue
178+
179+ # Skip the first line (title line)
180+ if "Per-node system memory usage" in line :
181+ continue
182+
183+ # Look for the header line with Node names and Total
184+ if not found_headers and ("Node" in line or "Total" in line ):
185+ # Parse headers by combining "Node" with following numbers
186+ parts = line .split ()
187+ headers = []
188+ i = 0
189+ while i < len (parts ):
190+ if parts [i ] == "Node" and i + 1 < len (parts ) and parts [i + 1 ].isdigit ():
191+ headers .append (f"Node { parts [i + 1 ]} " )
192+ i += 2
193+ elif parts [i ] == "Total" :
194+ headers .append ("Total" )
195+ i += 1
196+ else :
197+ i += 1
198+
199+ # Initialize dictionaries for each node/total
200+ for header in headers :
201+ numastat_dict [header ] = {}
202+ found_headers = True
203+ continue
204+
205+ # Skip separator lines (lines with dashes)
206+ if found_headers and "-" in line :
207+ continue
208+
209+ # Parse data lines
210+ if found_headers :
211+ parts = line .split ()
212+ if len (parts ) >= 2 :
213+ metric_name = parts [0 ]
214+ values = parts [1 :]
215+
216+ # Assign values to each node/total
217+ for i , value in enumerate (values ):
218+ if i < len (headers ): # Make sure we don't go out of bounds
219+ header = headers [i ]
220+ try :
221+ numastat_dict [header ][metric_name ] = float (value )
222+ except ValueError :
223+ # If conversion to float fails, store as string
224+ numastat_dict [header ][metric_name ] = value
225+
226+ return numastat_dict
227+
228+
229+ def get_ulimit ():
230+ ulimit_p = subprocess .Popen (
231+ "ulimit -a" , stdout = subprocess .PIPE , stderr = subprocess .PIPE , shell = True
232+ )
233+ (ulimit_data , err ) = ulimit_p .communicate ()
234+ ulimit_data = ulimit_data .decode ("utf-8" ).split ("\n " )
235+
236+ ulimit_dict = {}
237+
238+ for line in ulimit_data :
239+ line = line .strip ()
240+ if not line :
241+ continue
242+
243+ # Find the last occurrence of parentheses which contains the flag
244+ last_paren_start = line .rfind ("(" )
245+ last_paren_end = line .rfind (")" )
246+
247+ if last_paren_start == - 1 or last_paren_end == - 1 :
248+ continue
249+
250+ # Extract the description (everything before the last parentheses)
251+ description_part = line [:last_paren_start ].strip ()
252+
253+ # Extract the flag and unit (inside the last parentheses)
254+ flag_part = line [last_paren_start + 1 : last_paren_end ]
255+ # The flag is typically the last part after comma and space
256+ if ", " in flag_part :
257+ unit_part = flag_part .split (", " )[0 ] # Everything before the comma
258+ flag = flag_part .split (", " )[- 1 ] # Everything after the comma
259+ description = f"{ description_part } ({ unit_part } )"
260+ else :
261+ flag = flag_part
262+ description = description_part
263+
264+ # Extract the value (everything after the last parentheses)
265+ value_str = line [last_paren_end + 1 :].strip ()
266+
267+ # Try to convert value to appropriate type
268+ if value_str == "unlimited" :
269+ value = "unlimited"
270+ else :
271+ try :
272+ # Try integer first
273+ if "." not in value_str :
274+ value = int (value_str )
275+ else :
276+ value = float (value_str )
277+ except ValueError :
278+ # If conversion fails, keep as string
279+ value = value_str
280+
281+ ulimit_dict [description ] = {"flag" : flag , "value" : value }
282+
283+ return ulimit_dict
0 commit comments