1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-23 00:29:59 +02:00

update schema with nic, hyperv, and process changes

This commit is contained in:
Jon Smith
2021-04-14 08:59:17 -05:00
parent af74047b81
commit 14838f7f5d
9 changed files with 953 additions and 113 deletions

View File

@ -18,7 +18,7 @@ Compatibility:
Examples:
$ systeminfo | jc --systeminfo -p
$ systeminfo | jc --systeminfo -p -r
{
"host_name": "DESKTOP-WIN01",
"os_name": "Microsoft Windows 10 Enterprise",
@ -50,11 +50,97 @@ Examples:
"page_file_locations": "C:\\pagefile.sys",
"domain": "TEST.local",
"logon_server": "\\\\WIN-AA1A1A11AAA",
"hotfixs": ["KB4578968", "KB4562830", "KB4570334", "KB4580325", "KB4586864", "KB4594440"],
"network_cards": "1 NIC(s) Installed.\n [01]: Int...",
"hyperv_requirements": "A hypervisor has been detected. Features required fo..."
"hotfixs": [
"KB4578968",
"KB4562830",
"KB4570334",
"KB4580325",
"KB4586864",
"KB4594440"
],
"network_cards": [
{
"name": "Intel(R) 82574L Gigabit Network Connection",
"connection_name": "Ethernet0",
"status": "",
"dhcp_enabled": "Yes",
"dhcp_server": "192.168.133.250",
"ip_addresses": [
"192.168.133.3",
"fe80::192:eb64:1fcf:86eb"
]
}
],
"hyperv_requirements": {
"vm_monitor_mode_extensions": "Yes",
"virtualization_enabled_in_firmware": "Yes",
"second_level_address_translation": "No",
"data_execution_prevention_available": "Yes"
}
}
$ systeminfo | jc --systeminfo -p
{
"host_name": "DESKTOP-WIN01",
"os_name": "Microsoft Windows 10 Enterprise",
"os_version": "10.0.19042 N/A Build 19042",
"os_manufacturer": "Microsoft Corporation",
"os_configuration": "Member Workstation",
"os_build_type": "Multiprocessor Free",
"registered_owner": "User",
"registered_organization": "",
"product_id": "00111-12345-00001-AA111",
"original_install_date": 1613496027,
"system_boot_time": 1616163903,
"system_manufacturer": "VMware, Inc.",
"system_model": "VMware7,1",
"system_type": "x64-based PC",
"processors": ["Intel64 Family 6 Model 158 Stepping 13 GenuineIntel ~2400 Mhz"],
"bios_version": "VMware, Inc. VMW71.00V.11111111.B64.2008100111, 8/10/2020",
"windows_directory": "C:\\Windows",
"system_directory": "C:\\Windows\\system32",
"boot_device": "\\Device\\HarddiskVolume1",
"system_locale": "en-us;English (United States)",
"input_locale": "en-us;English (United States)",
"time_zone": "(UTC-08:00) Pacific Time (US & Canada)",
"total_physical_memory": 2047,
"available_physical_memory": 1417,
"virtual_memory_max_size": 2687,
"virtual_memory_available": 1482,
"virtual_memory_in_use": 1205",
"page_file_locations": "C:\\pagefile.sys",
"domain": "TEST.local",
"logon_server": "\\\\WIN-AA1A1A11AAA",
"hotfixs": [
"KB4578968",
"KB4562830",
"KB4570334",
"KB4580325",
"KB4586864",
"KB4594440"
],
"network_cards": [
{
"name": "Intel(R) 82574L Gigabit Network Connection",
"connection_name": "Ethernet0",
"status": "",
"dhcp_enabled": true,
"dhcp_server": "192.168.133.250",
"ip_addresses": [
"192.168.133.3",
"fe80::192:eb64:1fcf:86eb"
]
}
],
"hyperv_requirements": {
"vm_monitor_mode_extensions": "Yes",
"virtualization_enabled_in_firmware": "Yes",
"second_level_address_translation": "No",
"data_execution_prevention_available": "Yes"
}
}
"""
import re
import jc.utils
@ -79,53 +165,105 @@ def process(proc_data):
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
proc_data: (Dictionary) raw structured data to process
Returns:
List of Dictionaries. Some keys are optional. Example: a non-virtualized server will not have
the "hyperv_requirements" key. Structured data with the following schema:
Dictionary. Some keys are optional. Example: a non-virtualized server will an empty
"hyperv_requirements" object. Structured data with the following schema:
[
{
"host_name": "string",
"os_name": "string",
"os_version": "string",
"os_manufacturer": "string",
"os_configuration": "string",
"os_build_type": "string",
"registered_owner": "string",
"registered_organization": "string",
"product_id": "string",
"original_install_date": "string",
"system_boot_time": "string",
"system_manufacturer": "string",
"system_model": "string",
"system_type": "string",
"processors": ["string"],
"bios_version": "string",
"windows_directory": "string",
"system_directory": "string",
"boot_device": "string",
"system_locale": "string",
"input_locale": "string",
"time_zone": "string",
"total_physical_memory": "string",
"available_physical_memory": "string",
"virtual_memory_max_size": "string",
"virtual_memory_available": "string",
"virtual_memory_in_use": "string",
"page_file_locations": "string",
"domain": "string",
"logon_server": "string",
"hotfixs": ["string"],
"network_cards": "string",
"hyperv_requirements": "string"
{
"host_name": "string",
"os_name": "string",
"os_version": "string",
"os_manufacturer": "string",
"os_configuration": "string",
"os_build_type": "string",
"registered_owner": "string",
"registered_organization": "string",
"product_id": "string",
"original_install_date": integer, # naive timestamp
"system_boot_time": integer, # naive timestamp
"system_manufacturer": "string",
"system_model": "string",
"system_type": "string",
"processors": ["string"],
"bios_version": "string",
"windows_directory": "string",
"system_directory": "string",
"boot_device": "string",
"system_locale": "string",
"input_locale": "string",
"time_zone": "string",
"total_physical_memory": "string",
"available_physical_memory": integer,
"virtual_memory_max_size": integer,
"virtual_memory_available": integer,
"virtual_memory_in_use": integer,
"page_file_locations": "string",
"domain": "string",
"logon_server": "string",
"hotfixs": ["string"],
"network_cards": [
{
"name": "string",
"connection_name": "string",
"status": "string",
"dhcp_enabled": boolean,
"dhcp_server": "string",
"ip_addresses": ["string"]
}
],
"hyperv_requirements": {
"vm_monitor_mode_extensions": boolean,
"virtualization_enabled_in_firmware": boolean,
"second_level_address_translation": boolean,
"data_execution_prevention_available": boolean
}
]
}
"""
# rebuild output for added semantic information
for i, nic in enumerate(proc_data["network_cards"]):
proc_data["network_cards"][i]["dhcp_enabled"] = convert_to_boolean(
nic["dhcp_enabled"]
)
int_list = [
"total_physical_memory",
"available_physical_memory",
"virtual_memory_max_size",
"virtual_memory_available",
"virtual_memory_in_use",
]
for key in int_list:
proc_data[key] = convert_to_int(proc_data.get(key))
dt_list = ["original_install_date", "system_boot_time"]
for key in dt_list:
tz = proc_data.get("time_zone", "")
if tz:
# convert
# from: (UTC-08:00) Pacific Time (US & Canada)
# to: (UTC-0800)
tz_fields = tz.split(" ")
tz = " " + tz_fields[0].replace(":", "")
proc_data[key] = jc.utils.timestamp(f"{proc_data.get(key)}{tz}").naive
hyperv_key = "hyperv_requirements"
hyperv_subkey_list = [
"vm_monitor_mode_extensions",
"virtualization_enabled_in_firmware",
"second_level_address_translation",
"data_execution_prevention_available",
]
if hyperv_key in proc_data:
for key in hyperv_subkey_list:
if key in proc_data[hyperv_key]:
proc_data[hyperv_key][key] = convert_to_boolean(
proc_data[hyperv_key][key]
)
return proc_data
@ -176,12 +314,7 @@ def parse(data, raw=False, quiet=False):
# clean up keys; strip values
raw_output = {}
for k, v in raw_data.items():
# lowercase and replace spaces with underscores
k = k.strip().lower().replace(" ", "_")
# remove invalid key characters
for c in ";:!@#$%^&*()-":
k = k.replace(c, "")
k = transform_key(k)
# since we split on start_value_pos, the delimiter
# is still in the key field. Remove it.
@ -189,6 +322,10 @@ def parse(data, raw=False, quiet=False):
if k in ["hotfixs", "processors"]:
raw_output[k] = parse_hotfixs_or_processors(v)
elif k in ["network_cards"]:
raw_output[k] = parse_network_cards(v)
elif k in ["hyperv_requirements"]:
raw_output[k] = parse_hyperv_requirements(v)
else:
raw_output[k] = v.strip()
@ -227,9 +364,113 @@ def parse_hotfixs_or_processors(data):
return arr_output
def parse_hyperv_requirements(data):
"""
Turns a list of key/value settings for hyperv
into an object
Parameters:
data: (string) Input string
"""
output = {}
for i, l in enumerate(data.splitlines()):
if ":" in l:
k, v = l.split(":")
# discard the number sequence
output[transform_key(k)] = v.strip()
return output
def parse_network_cards(data):
"""
Turns a list of network_cards into an array of objects
Parameters:
data: (string) Input string
"""
delim = ":"
arr_output = []
cur_nic = None
is_ip = False
nic_value_pos = 0
for i, line in enumerate(data.splitlines()):
# skip first line
if i == 0:
continue
if "IP address(es)" in line:
is_ip = True
continue
cur_value_pos = len(line) - len(line.lstrip())
line = line.strip()
m = re.match(r"\[(\d+)\]" + delim + "(.+)", line)
if m and is_ip and cur_value_pos > nic_value_pos:
cur_nic["ip_addresses"].append(m.group(2).strip())
elif m:
if cur_nic:
arr_output.append(cur_nic)
cur_nic = default_nic()
cur_nic["name"] = m.group(2).strip()
nic_value_pos = cur_value_pos
is_ip = False
elif delim in line:
k, v = line.split(delim)
k = transform_key(k)
cur_nic[k] = v.strip()
if cur_nic:
arr_output.append(cur_nic)
return arr_output
def convert_to_boolean(value):
"""
Converts string input to boolean assuming "Yes/No" inputs
Parameters:
value: (string) Input value
"""
return value == "Yes"
def convert_to_int(value):
"""
Converts string input to integer by stripping all non-numeric characters
Parameters:
value: (string) Input value
"""
try:
value = int(re.sub("[^0-9]", "", value))
except ValueError:
pass
return value
def default_nic():
"""
Returns a default network card object
"""
return {
"name": "",
"connection_name": "",
"status": "",
"dhcp_enabled": "No",
"dhcp_server": "",
"ip_addresses": [],
}
def get_value_pos(line, delim):
"""
Finds the first non-whitespace character after the delimiter
Parameters:
line: (string) Input string
delim: (string) The data delimiter
@ -239,3 +480,19 @@ def get_value_pos(line, delim):
raise Exception(f"Expected a '{delim}' delimited field. Actual: {line}")
return len(line) - len(fields[1].lstrip())
def transform_key(key):
"""
Converts a given key to a valid json key that plays nice with jq
Parameters:
key: (string) Input value
"""
# lowercase and replace spaces with underscores
key = key.strip().lower().replace(" ", "_")
# remove invalid key characters
for c in ";:!@#$%^&*()-":
key = key.replace(c, "")
return key