diff --git a/salt/common/tools/sbin/so_logging_utils.py b/salt/common/tools/sbin/so_logging_utils.py new file mode 100644 index 000000000..dae734ac6 --- /dev/null +++ b/salt/common/tools/sbin/so_logging_utils.py @@ -0,0 +1,53 @@ +#!/usr/bin/python3 + +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + +import logging +import os +import sys + +def setup_logging(logger_name, log_file_path, log_level=logging.INFO, format_str='%(asctime)s - %(levelname)s - %(message)s'): + """ + Sets up logging for a script. + + Parameters: + logger_name (str): The name of the logger. + log_file_path (str): The file path for the log file. + log_level (int): The logging level (e.g., logging.INFO, logging.DEBUG). + format_str (str): The format string for log messages. + + Returns: + logging.Logger: Configured logger object. + """ + logger = logging.getLogger(logger_name) + logger.setLevel(log_level) + + # Create directory for log file if it doesn't exist + log_file_dir = os.path.dirname(log_file_path) + if log_file_dir and not os.path.exists(log_file_dir): + try: + os.makedirs(log_file_dir) + except OSError as e: + print(f"Error creating directory {log_file_dir}: {e}") + sys.exit(1) + + # Create handlers + c_handler = logging.StreamHandler() + f_handler = logging.FileHandler(log_file_path) + c_handler.setLevel(log_level) + f_handler.setLevel(log_level) + + # Create formatter and add it to handlers + formatter = logging.Formatter(format_str) + c_handler.setFormatter(formatter) + f_handler.setFormatter(formatter) + + # Add handlers to the logger if they are not already added + if not logger.hasHandlers(): + logger.addHandler(c_handler) + logger.addHandler(f_handler) + + return logger diff --git a/salt/hypervisor/tools/sbin/so-kvm-modify-hardware b/salt/hypervisor/tools/sbin/so-kvm-modify-hardware index 7bbb500af..cf4c20c49 100644 --- a/salt/hypervisor/tools/sbin/so-kvm-modify-hardware +++ b/salt/hypervisor/tools/sbin/so-kvm-modify-hardware @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/python3 # Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one # or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at @@ -16,31 +16,12 @@ Example: """ import argparse -import logging import sys -import time import libvirt +import logging import xml.etree.ElementTree as ET - -def setup_logging(): - logger = logging.getLogger('so-kvm-modify-hardware') - logger.setLevel(logging.INFO) - - # Create handlers - c_handler = logging.StreamHandler() - f_handler = logging.FileHandler('/opt/so/log/hypervisor/so-kvm-modify-hardware.log') - c_handler.setLevel(logging.INFO) - f_handler.setLevel(logging.INFO) - - # Create formatter and add it to handlers - formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') - c_handler.setFormatter(formatter) - f_handler.setFormatter(formatter) - - # Add handlers to the logger - logger.addHandler(c_handler) - logger.addHandler(f_handler) - return logger +from so_vm_utils import start_vm, stop_vm +from so_logging_utils import setup_logging def parse_arguments(): parser = argparse.ArgumentParser(description='Modify hardware parameters of a KVM virtual machine.') @@ -52,23 +33,6 @@ def parse_arguments(): args = parser.parse_args() return args -def stop_vm(conn, vm_name, logger): - try: - dom = conn.lookupByName(vm_name) - if dom.isActive(): - logger.info(f"Shutting down VM '{vm_name}'...") - dom.shutdown() - # Wait for the VM to shut down - while dom.isActive(): - time.sleep(1) - logger.info(f"VM '{vm_name}' has been stopped.") - else: - logger.info(f"VM '{vm_name}' is already stopped.") - return dom - except libvirt.libvirtError as e: - logger.error(f"Failed to stop VM '{vm_name}': {e}") - sys.exit(1) - def modify_vm(dom, cpu_count, memory_amount, pci_id, logger): try: # Get the XML description of the VM @@ -136,17 +100,8 @@ def redefine_vm(conn, new_xml_desc, logger): logger.error(f"Failed to redefine VM: {e}") sys.exit(1) -def start_vm(dom, logger): - try: - dom.create() - logger.info("VM started successfully.") - except libvirt.libvirtError as e: - logger.error(f"Failed to start VM: {e}") - sys.exit(1) - def main(): try: - logger = setup_logging() args = parse_arguments() vm_name = args.vm @@ -155,6 +110,14 @@ def main(): pci_id = args.pci start_vm_flag = args.start + # Set up logging using the so_logging_utils library + logger = setup_logging( + logger_name='so-kvm-modify-hardware', + log_file_path='/opt/so/log/hypervisor/so-kvm-modify-hardware.log', + log_level=logging.INFO, + format_str='%(asctime)s - %(levelname)s - %(message)s' + ) + # Connect to libvirt try: conn = libvirt.open(None) diff --git a/salt/hypervisor/tools/sbin/so-qcow2-modify-network b/salt/hypervisor/tools/sbin/so-qcow2-modify-network index 7d4612730..6ec83d3e3 100644 --- a/salt/hypervisor/tools/sbin/so-qcow2-modify-network +++ b/salt/hypervisor/tools/sbin/so-qcow2-modify-network @@ -6,14 +6,15 @@ # Elastic License 2.0. """ -Script to modify the NetworkManager config within a qcow2 image. +Script to modify the NetworkManager config within a QCOW2 image. Usage: - python so-qcow2-modify-network.py -v [-c ] [-m ] [-p ] + python so-qcow2-modify-network.py -I -i (--dhcp4 | --static4 --ip4 --gw4 ) [--dns4 ] [--search4 ] -Example: - python so-qcow2-modify-network.py -I path_to_image -i interface --static4 --ip4 192.168.1.10 --gw4 192.168.1.1 --dns4 192.168.1.1,8.8.8.8 --seearch4 example.local - python so-qcow2-modify-network.py -I path_to_image -i interface --dhcp4 +Examples: + python so-qcow2-modify-network.py -I path_to_image -i eth0 --static4 --ip4 192.168.1.10/24 --gw4 192.168.1.1 --dns4 192.168.1.1,8.8.8.8 --search4 example.local + + python so-qcow2-modify-network.py -I path_to_image -i eth0 --dhcp4 """ import argparse @@ -25,29 +26,11 @@ import os import ipaddress import configparser from io import StringIO +from so_logging_utils import setup_logging + NETWORK_CONFIG_DIR = "/etc/NetworkManager/system-connections" -def setup_logging(): - logger = logging.getLogger('so-qcow2-modify-network') - logger.setLevel(logging.INFO) - - # Create handlers - c_handler = logging.StreamHandler() - f_handler = logging.FileHandler('/opt/so/log/hypervisor/so-qcow2-modify-network.log') - c_handler.setLevel(logging.INFO) - f_handler.setLevel(logging.INFO) - - # Create formatter and add it to handlers - formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') - c_handler.setFormatter(formatter) - f_handler.setFormatter(formatter) - - # Add handlers to the logger - logger.addHandler(c_handler) - logger.addHandler(f_handler) - return logger - def validate_ip_address(ip_str, description="IP address"): try: ipaddress.IPv4Interface(ip_str) @@ -179,7 +162,13 @@ def parse_arguments(): def main(): try: - logger = setup_logging() + # Set up logging using the so_logging_utils library + logger = setup_logging( + logger_name='so-qcow2-modify-network', + log_file_path='/opt/so/log/hypervisor/so-qcow2-modify-network.log', + log_level=logging.INFO, + format_str='%(asctime)s - %(levelname)s - %(message)s' + ) args = parse_arguments() validate_interface_name(args.interface) diff --git a/salt/hypervisor/tools/sbin/so_vm_utils.py b/salt/hypervisor/tools/sbin/so_vm_utils.py new file mode 100644 index 000000000..a6820b885 --- /dev/null +++ b/salt/hypervisor/tools/sbin/so_vm_utils.py @@ -0,0 +1,60 @@ +#!/usr/bin/python3 + +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + +import sys +import time +import libvirt +import logging + +def stop_vm(conn, vm_name, logger): + """ + Stops the specified virtual machine if it is running. + + Parameters: + conn (libvirt.virConnect): The libvirt connection object. + vm_name (str): The name of the virtual machine. + logger (logging.Logger): The logger object. + + Returns: + libvirt.virDomain: The domain object of the VM. + + Raises: + SystemExit: If the VM cannot be found or an error occurs. + """ + try: + dom = conn.lookupByName(vm_name) + if dom.isActive(): + logger.info(f"Shutting down VM '{vm_name}'...") + dom.shutdown() + # Wait for the VM to shut down + while dom.isActive(): + time.sleep(1) + logger.info(f"VM '{vm_name}' has been stopped.") + else: + logger.info(f"VM '{vm_name}' is already stopped.") + return dom + except libvirt.libvirtError as e: + logger.error(f"Failed to stop VM '{vm_name}': {e}") + sys.exit(1) + +def start_vm(dom, logger): + """ + Starts the specified virtual machine. + + Parameters: + dom (libvirt.virDomain): The domain object of the VM. + logger (logging.Logger): The logger object. + + Raises: + SystemExit: If the VM cannot be started. + """ + try: + dom.create() + logger.info(f"VM '{dom.name()}' started successfully.") + except libvirt.libvirtError as e: + logger.error(f"Failed to start VM '{dom.name()}': {e}") + sys.exit(1)