mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-25 10:13:01 +02:00
Merge pull request #1288 from kernelkit/misc
Fix 'show dhcp-server' output in CLI and operational
This commit is contained in:
+11
@@ -113,6 +113,16 @@
|
||||
{"id": "vendor-class", "value": "Banana Pi BPI-R3"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-ip:ipv6": {
|
||||
"infix-dhcpv6-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "ntp-server"},
|
||||
{"id": "client-fqdn"},
|
||||
{"id": "domain-search"},
|
||||
{"id": "dns-server"}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -284,6 +294,7 @@
|
||||
"policy": [
|
||||
{
|
||||
"name": "lan-to-wan",
|
||||
"action": "accept",
|
||||
"ingress": [
|
||||
"lan"
|
||||
],
|
||||
|
||||
+11
@@ -72,6 +72,16 @@
|
||||
{"id": "vendor-class", "value": "NanoPi R2S"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-ip:ipv6": {
|
||||
"infix-dhcpv6-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "ntp-server"},
|
||||
{"id": "client-fqdn"},
|
||||
{"id": "domain-search"},
|
||||
{"id": "dns-server"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -235,6 +245,7 @@
|
||||
"policy": [
|
||||
{
|
||||
"name": "lan-to-wan",
|
||||
"action": "accept",
|
||||
"ingress": [
|
||||
"lan"
|
||||
],
|
||||
|
||||
@@ -68,6 +68,9 @@ All notable changes to the project are documented in this file.
|
||||
- Add support for property-based filtering with operators (contains, isequal,
|
||||
startswith, regex, ereregex) on message properties (msg, msgid, programname,
|
||||
hostname, source, data), with optional case-insensitive and negate modifiers
|
||||
- Update factory configuration for BPi-R3 and NanoPi R2S boards to enable
|
||||
DHCPv6 client on WAN interface and allow traffic forwarding from LAN to WAN
|
||||
zone in the firewall (this is what most users expect)
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -80,6 +83,12 @@ All notable changes to the project are documented in this file.
|
||||
- Fix #1255: serious regression in boot time, introduced in v25.10, delays the
|
||||
boot step "Mounting filesystems ...", from 30 seconds up to five minutes!
|
||||
- Fix broken intra-document links in container and tunnel documentation
|
||||
- Fix `show dhcp-server` command crashing with invalid timestamp format.
|
||||
DHCP lease expiry timestamps had double timezone suffix causing libyang
|
||||
validation errors
|
||||
- Fix `show dhcp-server` output alignment. The EXPIRES column was misaligned
|
||||
when CLIENT ID field was empty, and CLIENT ID column was too narrow for
|
||||
typical 20-character client IDs
|
||||
|
||||
[latest-boot]: https://github.com/kernelkit/infix/releases/latest-boot
|
||||
[bpi-r3-emmc-documentation]: https://github.com/kernelkit/infix/blob/main/board/aarch64/bananapi-bpi-r3/README.md
|
||||
|
||||
@@ -154,7 +154,7 @@ class PadDhcpServer:
|
||||
ip = 17
|
||||
mac = 19
|
||||
host = 21
|
||||
cid = 19
|
||||
cid = 22
|
||||
exp = 10
|
||||
|
||||
|
||||
@@ -652,7 +652,20 @@ class Sensor:
|
||||
else:
|
||||
return f"{self.value} W"
|
||||
|
||||
# Handle PWM fan sensors (reported as "other" type with milli scale)
|
||||
# PWM duty cycle is reported as percentage (0-100)
|
||||
elif self.value_type == 'other' and self.value_scale == 'milli':
|
||||
# Check if this is likely a PWM sensor based on description or name
|
||||
name_lower = self.name.lower()
|
||||
desc_lower = (self.description or "").lower()
|
||||
if 'pwm' in desc_lower or 'fan' in name_lower or 'fan' in desc_lower:
|
||||
percent = self.value / 1000.0
|
||||
return f"{percent:.1f}%"
|
||||
# Fall through for other "other" type sensors
|
||||
|
||||
# For unknown sensor types, show raw value
|
||||
if self.value_type in ['other', 'unknown']:
|
||||
return f"{self.value}"
|
||||
else:
|
||||
return f"{self.value} {self.value_type}"
|
||||
|
||||
@@ -720,11 +733,11 @@ class DhcpServer:
|
||||
now = datetime.now(timezone.utc)
|
||||
for lease in get_json_data([], self.data, 'leases', 'lease'):
|
||||
if lease["expires"] == "never":
|
||||
exp = " never"
|
||||
exp = "never"
|
||||
else:
|
||||
dt = datetime.strptime(lease['expires'], '%Y-%m-%dT%H:%M:%S%z')
|
||||
seconds = int((dt - now).total_seconds())
|
||||
exp = f" {self.format_duration(seconds)}"
|
||||
exp = self.format_duration(seconds)
|
||||
self.leases.append({
|
||||
"ip": lease["address"],
|
||||
"mac": lease["phys-address"],
|
||||
@@ -775,7 +788,7 @@ class DhcpServer:
|
||||
row += f"{mac:<{PadDhcpServer.mac}}"
|
||||
row += f"{host:<{PadDhcpServer.host}}"
|
||||
row += f"{cid:<{PadDhcpServer.cid}}"
|
||||
row += f"{exp:>{PadDhcpServer.exp - 1}}"
|
||||
row += f"{exp:>{PadDhcpServer.exp}}"
|
||||
print(row)
|
||||
|
||||
def print_stats(self):
|
||||
|
||||
@@ -297,7 +297,7 @@ def hwmon_sensor_components():
|
||||
except (FileNotFoundError, ValueError, IOError):
|
||||
continue
|
||||
|
||||
# Fan sensors
|
||||
# Fan sensors (RPM from tachometer)
|
||||
for fan_file in glob.glob(os.path.join(hwmon_path, "fan*_input")):
|
||||
try:
|
||||
sensor_num = os.path.basename(fan_file).split('_')[0].replace('fan', '')
|
||||
@@ -314,6 +314,36 @@ def hwmon_sensor_components():
|
||||
except (FileNotFoundError, ValueError, IOError):
|
||||
continue
|
||||
|
||||
# PWM fan sensors (duty cycle percentage)
|
||||
# Only add if no fan*_input exists for this device (avoid duplicates)
|
||||
has_rpm_sensor = bool(glob.glob(os.path.join(hwmon_path, "fan*_input")))
|
||||
if not has_rpm_sensor:
|
||||
for pwm_file in glob.glob(os.path.join(hwmon_path, "pwm[0-9]*")):
|
||||
# Skip pwm*_enable, pwm*_mode, etc. - only process pwm1, pwm2, etc.
|
||||
pwm_basename = os.path.basename(pwm_file)
|
||||
if not pwm_basename.replace('pwm', '').isdigit():
|
||||
continue
|
||||
try:
|
||||
sensor_num = pwm_basename.replace('pwm', '')
|
||||
pwm_raw = int(HOST.read(pwm_file).strip())
|
||||
# Convert PWM duty cycle (0-255) to percentage (0-100)
|
||||
# Note: Some devices are inverted (255=off, 0=max), but we report as-is
|
||||
# The value represents duty cycle, not necessarily fan speed
|
||||
# Use "other" value-type since PWM duty cycle isn't a standard IETF type
|
||||
value = int((pwm_raw / 255.0) * 100 * 1000) # Convert to milli-percent (0-100000)
|
||||
label_file = os.path.join(hwmon_path, f"pwm{sensor_num}_label")
|
||||
raw_label = None
|
||||
if HOST.exists(label_file):
|
||||
raw_label = HOST.read(label_file).strip()
|
||||
label = normalize_sensor_name(raw_label)
|
||||
sensor_name = f"{base_name}-{label}"
|
||||
else:
|
||||
sensor_name = base_name if sensor_num == '1' else f"{base_name}{sensor_num}"
|
||||
# Use "PWM Fan" as description so it displays nicely in show hardware
|
||||
add_sensor(base_name, create_sensor(sensor_name, value, "other", "milli", raw_label or "PWM Fan"))
|
||||
except (FileNotFoundError, ValueError, IOError):
|
||||
continue
|
||||
|
||||
# Voltage sensors
|
||||
for voltage_file in glob.glob(os.path.join(hwmon_path, "in*_input")):
|
||||
try:
|
||||
|
||||
@@ -23,7 +23,7 @@ def leases(leases_file):
|
||||
else:
|
||||
dt = datetime.fromtimestamp(int(tokens[0]),
|
||||
tz=timezone.utc)
|
||||
expires = dt.isoformat() + "+00:00"
|
||||
expires = dt.isoformat()
|
||||
|
||||
row = {
|
||||
"expires": expires,
|
||||
|
||||
Reference in New Issue
Block a user