284 lines
9.7 KiB
Diff
284 lines
9.7 KiB
Diff
|
commit 44853a940a2b3c52395e26a3632e10cc6b5f2e5d
|
||
|
Author: Neil Horman <nhorman@tuxdriver.com>
|
||
|
Date: Thu Jun 27 11:26:48 2019 -0400
|
||
|
|
||
|
Add support for multiple type 42 blocks in SMBIOS
|
||
|
|
||
|
DMTF recently updated their host API specification to allow for multiple
|
||
|
type 42 blocks (in support of ipv4/ipv6 in the constrained space of a
|
||
|
single block). Enhance redfish-finder to parse and merge those blocks
|
||
|
|
||
|
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
|
||
|
|
||
|
diff --git a/redfish-finder b/redfish-finder
|
||
|
index 45c4ea8..429cc42 100755
|
||
|
--- a/redfish-finder
|
||
|
+++ b/redfish-finder
|
||
|
@@ -1,4 +1,4 @@
|
||
|
-#!/usr/bin/python3
|
||
|
+#!/usr/libexec/platform-python
|
||
|
|
||
|
import sys
|
||
|
import os
|
||
|
@@ -49,6 +49,9 @@ class NetDevice(object):
|
||
|
def getifcname(self):
|
||
|
return self.name
|
||
|
|
||
|
+ def merge(self, newdev):
|
||
|
+ return self
|
||
|
+
|
||
|
def __str__(self):
|
||
|
return "Interface: " + self.name
|
||
|
|
||
|
@@ -112,9 +115,9 @@ class USBNetDevice(NetDevice):
|
||
|
######################################################
|
||
|
class HostConfig():
|
||
|
def __init__(self, cursor):
|
||
|
- self.address = None
|
||
|
- self.mask = None
|
||
|
- self.network = None
|
||
|
+ self.address = []
|
||
|
+ self.mask = []
|
||
|
+ self.network = []
|
||
|
|
||
|
try:
|
||
|
cursor = cursor_consume_next(cursor, "Host IP Assignment Type: ")
|
||
|
@@ -122,26 +125,30 @@ class HostConfig():
|
||
|
printf("redfish-finder: Unable to parse SMBIOS Host IP Assignment Type")
|
||
|
return None
|
||
|
if cursor.split()[0] == "Static":
|
||
|
- self.assigntype = AssignType.STATIC
|
||
|
+ self.assigntype = []
|
||
|
+ self.assigntype.append(AssignType.STATIC)
|
||
|
cursor = cursor_consume_next(cursor, "Host IP Address Format: ")
|
||
|
if cursor.split()[0] == "IPv4":
|
||
|
cursor = cursor_consume_next(cursor, "IPv4 Address: ")
|
||
|
addr = cursor.split()[0]
|
||
|
- self.address = ipaddress.IPv4Address(addr)
|
||
|
+ self.address.append(ipaddress.IPv4Address(addr))
|
||
|
cursor = cursor_consume_next(cursor, "IPv4 Mask: ")
|
||
|
mask = cursor.split()[0]
|
||
|
- self.mask = ipaddress.IPv4Address(mask)
|
||
|
- self.network = ipaddress.IPv4Network(addr + "/" + mask, strict=False)
|
||
|
+ self.mask.append(ipaddress.IPv4Address(mask))
|
||
|
+ self.network.append(ipaddress.IPv4Network(addr + "/" + mask, strict=False))
|
||
|
elif cursor.split()[0] == "IPv6":
|
||
|
cursor = cursor_consume_next(cursor, "IPv6 Address: ")
|
||
|
addr = cursor.split()[0]
|
||
|
- self.address = ipaddress.IPv6Address(addr)
|
||
|
+ self.address.append(ipaddress.IPv6Address(addr))
|
||
|
cursor = cursor_consume_next(cursor, "IPv6 Mask: ")
|
||
|
mask = cursor.split()[0]
|
||
|
- self.mask = ipaddress.IPv4Address(mask)
|
||
|
- self.network = ipaddress.IPv6Network(addr + "/" + mask, strict=False)
|
||
|
+ self.mask.append(ipaddress.IPv4Address(mask))
|
||
|
+ self.network.append(ipaddress.IPv6Network(addr + "/" + mask, strict=False))
|
||
|
elif cursor.split()[0] == "DHCP":
|
||
|
- self.assigntype = AssignType.DHCP
|
||
|
+ self.assigntype.append(AssignType.DHCP)
|
||
|
+ self.address.append(0)
|
||
|
+ self.mask.append(0)
|
||
|
+ self.network.append(0)
|
||
|
else:
|
||
|
# Support the other types later
|
||
|
print("redfish-finder: Unable to parse SMBIOS Host configuaration")
|
||
|
@@ -150,6 +157,13 @@ class HostConfig():
|
||
|
print("redfish-finder: Unexpected error while parsing HostConfig!")
|
||
|
return None
|
||
|
|
||
|
+ def merge(self, newconfig):
|
||
|
+ self.assigntype.extend(newconfig.assigntype)
|
||
|
+ self.address.extend(newconfig.address)
|
||
|
+ self.mask.extend(newconfig.mask)
|
||
|
+ self.network.extend(newconfig.network)
|
||
|
+ return self
|
||
|
+
|
||
|
#
|
||
|
# Using the smbios host config info, set the appropriate
|
||
|
# attributes of the network manager connection object
|
||
|
@@ -157,20 +171,22 @@ class HostConfig():
|
||
|
def generate_nm_config(self, device, nmcon):
|
||
|
assignmap = { AssignType.STATIC: "manual", AssignType.DHCP: "auto"}
|
||
|
methodp = "ipv4.method"
|
||
|
- if self.assigntype == AssignType.STATIC:
|
||
|
- if self.address.version == 4:
|
||
|
- methodp = "ipv4.method"
|
||
|
- addrp = "ipv4.addresses"
|
||
|
- else:
|
||
|
- methodp = "ipv6.method"
|
||
|
- addrp = "ipv6.addresses"
|
||
|
- try:
|
||
|
- nmcon.update_property(methodp, assignmap[self.assigntype])
|
||
|
- if self.assigntype == AssignType.STATIC:
|
||
|
- nmcon.update_property(addrp, str(self.address) + "/" + str(self.network.prefixlen))
|
||
|
- except:
|
||
|
- print("redfish-finder: Error generating nm_config")
|
||
|
- return False
|
||
|
+ for i in range(len(self.assigntype)):
|
||
|
+ assigntype = self.assigntype[i]
|
||
|
+ if assigntype == AssignType.STATIC:
|
||
|
+ if self.address[i].version == 4:
|
||
|
+ methodp = "ipv4.method"
|
||
|
+ addrp = "ipv4.addresses"
|
||
|
+ else:
|
||
|
+ methodp = "ipv6.method"
|
||
|
+ addrp = "ipv6.addresses"
|
||
|
+ try:
|
||
|
+ nmcon.update_property(methodp, assignmap[assigntype])
|
||
|
+ if assigntype == AssignType.STATIC:
|
||
|
+ nmcon.update_property(addrp, str(self.address[i]) + "/" + str(self.network[i].prefixlen))
|
||
|
+ except:
|
||
|
+ print("redfish-finder: Error generating nm_config")
|
||
|
+ return False
|
||
|
|
||
|
return True
|
||
|
|
||
|
@@ -188,8 +204,8 @@ class HostConfig():
|
||
|
######################################################
|
||
|
class ServiceConfig():
|
||
|
def __init__(self, cursor):
|
||
|
- self.address = None
|
||
|
- self.mask = None
|
||
|
+ self.address = []
|
||
|
+ self.mask = []
|
||
|
try:
|
||
|
cursor = cursor_consume_next(cursor, "Redfish Service IP Discovery Type: ")
|
||
|
if cursor == None:
|
||
|
@@ -200,14 +216,14 @@ class ServiceConfig():
|
||
|
cursor = cursor_consume_next(cursor, "Redfish Service IP Address Format: ")
|
||
|
if cursor.split()[0] == "IPv4":
|
||
|
cursor = cursor_consume_next(cursor, "IPv4 Redfish Service Address: ")
|
||
|
- self.address = ipaddress.IPv4Address(cursor.split()[0])
|
||
|
+ self.address.append(ipaddress.IPv4Address(cursor.split()[0]))
|
||
|
cursor = cursor_consume_next(cursor, "IPv4 Redfish Service Mask: ")
|
||
|
- self.mask = ipaddress.IPv4Address(cursor.split()[0])
|
||
|
+ self.mask.append(ipaddress.IPv4Address(cursor.split()[0]))
|
||
|
elif cursor.split()[0] == "IPv6":
|
||
|
cursor = cursor_consume_next(cursor, "IPv6 Redfish Service Address: ")
|
||
|
- self.address = ipaddress.IPv6Address(unicode(cursor.split()[0], "utf-8"))
|
||
|
+ self.address.append(ipaddress.IPv6Address(unicode(cursor.split()[0], "utf-8")))
|
||
|
cursor = cursor_consume_next(cursor, "IPv6 Mask: ")
|
||
|
- self.mask = ipaddress.IPv4Address(unicode(cursor.split()[0], "utf-8"))
|
||
|
+ self.mask.append(ipaddress.IPv4Address(unicode(cursor.split()[0], "utf-8")))
|
||
|
elif cursor.split()[0] == "DHCP":
|
||
|
self.assigntype = AssignType.DHCP
|
||
|
else:
|
||
|
@@ -223,6 +239,11 @@ class ServiceConfig():
|
||
|
except:
|
||
|
print("redfish-finder: Unexpected error parsing ServiceConfig")
|
||
|
|
||
|
+ def merge(self, newconfig):
|
||
|
+ self.address.extend(newconfig.address)
|
||
|
+ self.mask.extend(newconfig.mask)
|
||
|
+ return self
|
||
|
+
|
||
|
def __str__(self):
|
||
|
val = "Service Config(" + AssignType.typestring[self.assigntype] + ")"
|
||
|
if (self.assigntype == AssignType.STATIC):
|
||
|
@@ -236,42 +257,63 @@ class ServiceConfig():
|
||
|
######################################################
|
||
|
class dmiobject():
|
||
|
def __init__(self, dmioutput):
|
||
|
+ self.device = None
|
||
|
+ self.hostconfig = None
|
||
|
+ self.serviceconfig = None
|
||
|
cursor = dmioutput
|
||
|
# Find the type 42 header, if not found, nothing to do here
|
||
|
- cursor = cursor_consume_next(cursor, "Management Controller Host Interface\n")
|
||
|
- if (cursor == None):
|
||
|
- return None
|
||
|
- cursor = cursor_consume_next(cursor, "Host Interface Type: Network\n")
|
||
|
- if (cursor == None):
|
||
|
- return None
|
||
|
+ cursor = cursor_consume_next(cursor, "Management Controller Host Interface\n")
|
||
|
+ while (cursor != None):
|
||
|
+ if (cursor == None):
|
||
|
+ return None
|
||
|
+ cursor = cursor_consume_next(cursor, "Host Interface Type: Network\n")
|
||
|
+ if (cursor == None):
|
||
|
+ return None
|
||
|
|
||
|
- # If we get here then we know this is a network interface device
|
||
|
- cursor = cursor_consume_next(cursor, "Device Type: ")
|
||
|
- # The next token should either be:
|
||
|
- # USB
|
||
|
- # PCI/PCIe
|
||
|
- # OEM
|
||
|
- # Unknown
|
||
|
- dtype = cursor.split()[0]
|
||
|
- if (dtype == "USB"):
|
||
|
- self.device = USBNetDevice(cursor)
|
||
|
-
|
||
|
- if self.device == None:
|
||
|
- return None
|
||
|
+ # If we get here then we know this is a network interface device
|
||
|
+ cursor = cursor_consume_next(cursor, "Device Type: ")
|
||
|
+ # The next token should either be:
|
||
|
+ # USB
|
||
|
+ # PCI/PCIe
|
||
|
+ # OEM
|
||
|
+ # Unknown
|
||
|
+ dtype = cursor.split()[0]
|
||
|
+ if (dtype == "USB"):
|
||
|
+ newdev = USBNetDevice(cursor)
|
||
|
+
|
||
|
+ if newdev == None:
|
||
|
+ return None
|
||
|
|
||
|
- # Now find the Redfish over IP section
|
||
|
- cursor = cursor_consume_next(cursor, "Protocol ID: 04 (Redfish over IP)\n")
|
||
|
- if (cursor == None):
|
||
|
- print("redfish-finder: Unable to find Redfish Protocol")
|
||
|
- return None
|
||
|
+ if self.device == None:
|
||
|
+ self.device = newdev
|
||
|
+ else:
|
||
|
+ self.device.merge(newdev)
|
||
|
|
||
|
- self.hostconfig = HostConfig(cursor)
|
||
|
- if self.hostconfig == None:
|
||
|
- return None
|
||
|
+ # Now find the Redfish over IP section
|
||
|
+ cursor = cursor_consume_next(cursor, "Protocol ID: 04 (Redfish over IP)\n")
|
||
|
+ if (cursor == None):
|
||
|
+ print("redfish-finder: Unable to find Redfish Protocol")
|
||
|
+ return None
|
||
|
|
||
|
- self.serviceconfig = ServiceConfig(cursor)
|
||
|
- if self.serviceconfig == None:
|
||
|
- return None
|
||
|
+ newhostconfig = HostConfig(cursor)
|
||
|
+ if newhostconfig == None:
|
||
|
+ return None
|
||
|
+
|
||
|
+ if self.hostconfig == None:
|
||
|
+ self.hostconfig = newhostconfig
|
||
|
+ else:
|
||
|
+ self.hostconfig.merge(newhostconfig)
|
||
|
+
|
||
|
+ serviceconfig = ServiceConfig(cursor)
|
||
|
+ if serviceconfig == None:
|
||
|
+ return None
|
||
|
+
|
||
|
+ if self.serviceconfig == None:
|
||
|
+ self.serviceconfig = serviceconfig
|
||
|
+ elif self.serviceconfig == None:
|
||
|
+ self.serviceconfig.merge(serviceconfig)
|
||
|
+
|
||
|
+ cursor = cursor_consume_next(cursor, "Management Controller Host Interface\n")
|
||
|
|
||
|
|
||
|
def __str__(self):
|
||
|
@@ -309,7 +351,10 @@ class OSServiceData():
|
||
|
continue
|
||
|
|
||
|
# Now add the new entries in
|
||
|
- newentry = str(self.sconf.address) + " " + self.constant_name
|
||
|
+ addresses=""
|
||
|
+ for i in self.sconf.address:
|
||
|
+ addresses = addresses + str(i) + " "
|
||
|
+ newentry = addresses + " " + self.constant_name
|
||
|
newentry = newentry + " " + self.sconf.hostname
|
||
|
self.host_entries.append(newentry)
|
||
|
|