Skip to content

Commit

Permalink
Merge pull request #39 from redBorder/development
Browse files Browse the repository at this point in the history
Release 2.1.0
  • Loading branch information
manegron authored Oct 7, 2024
2 parents 498a07e + fd4f7f3 commit 201f397
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 1 deletion.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.1
2.1.0
260 changes: 260 additions & 0 deletions resources/scripts/rb_change_segments.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
#!/usr/bin/env ruby

require 'json'
require 'mrdialog'
require 'yaml'
require 'logger'
require 'getopt/std'
require "#{ENV['RBLIB']}/rb_wiz_lib"
require "#{ENV['RBLIB']}/rb_config_utils.rb"

CONFFILE = "#{ENV['RBETC']}/rb_init_conf.yml" unless defined?(CONFFILE)
DIALOGRC = "#{ENV['RBETC']}/dialogrc"
ENV['DIALOGRC'] = DIALOGRC if File.exist?(DIALOGRC)

opt = Getopt::Std.getopts("f")

def cancel_change_segments()

dialog = MRDialog.new
dialog.clear = true
dialog.title = "Segments change wizard cancelled"

text = <<EOF
The segments change has been cancelled or stopped.
If you want to complete the change, please execute it again.
EOF
result = dialog.msgbox(text, 11, 41)
exit(1)

end

# Display a warning dialog to the user if not in a local tty.
#
# This function uses `MRDialog` to create a dialog window. If the script is not being run in a local TTY, this message is shown.
# @example
# local_tty_warning_wizard unless Config_utils.is_local_tty or opt["f"]
def local_tty_warning_wizard
dialog = MRDialog.new
dialog.clear = true
dialog.title = "SETUP wizard cancelled"

text = <<EOF
This device must be configured under local tty.
If you want to complete the setup wizard, please execute it again in a local tty.
EOF
result = dialog.msgbox(text, 11, 41)
exit(1)
end

# Run the wizard only in local tty
local_tty_warning_wizard unless Config_utils.is_local_tty or opt["f"]

# Load configuration from a YAML file.
#
# @param file [String] the path to the YAML configuration file.
# @return [Hash] the configuration loaded from the file, or an empty hash if loading fails.
def load_config(file)
YAML.load_file(file) rescue {}
end

# Save configuration to a YAML file.
#
# @param file [String] the path to the YAML file where the configuration will be saved.
# @param config [Hash] the configuration data to save.
def save_config(file, config)
File.open(file, 'w') { |f| f.write(config.to_yaml) }
end

# Display the current segment configuration before deletion using a dialog.
#
# This function uses `MRDialog` to show the segment configuration to the user.
def show_current_segments_config_dialog(config)
dialog = MRDialog.new
dialog.clear = true
dialog.title = "Current Segment Configuration"

if config["segments"].nil? || config["segments"].empty?
text = "No segments are currently configured."
else
text = "Current Segment Configuration:\n\n"
config["segments"].each do |segment|
text += "Segment: #{segment['name']}\n"
text += "Ports: #{segment['ports'].join(', ')}\n"
text += "-----------------------\n"
end
end

# Display the dialog with the configuration
dialog.msgbox(text, 15, 50)
end

# Load the current configuration from the config file
init_conf = load_config(CONFFILE)

# Display segment configuration before any action
show_current_segments_config_dialog(init_conf)

# Display a warning dialog to the user about deleting all network segment configurations.
#
# This function uses `MRDialog` to create a dialog window. If the user selects 'No', the program exits.
def warn_user_about_segment_deletion
dialog = MRDialog.new
dialog.clear = true
dialog.title = "Warning: Delete All Segments"
text = "All existing network segment configurations will be deleted.\nThis action cannot be undone.\nDo you want to continue?"
choice = dialog.yesno(text, 10, 50)
exit(1) if choice == false
end

# Delete all existing bridge interfaces from the system.
#
# This function removes all network bridge interfaces that start with "br".
def delete_existing_br_interfaces
br_interfaces = Dir.entries("/sys/class/net/").select { |f| f.start_with?("br") }
br_interfaces.each do |br_iface|
system("ip link set #{br_iface} down")
system("brctl delbr #{br_iface}")
end
end

warn_user_about_segment_deletion
delete_existing_br_interfaces

init_conf = load_config(CONFFILE)

segments_conf = SegmentsConf.new
segments_conf.doit
init_conf["segments"] = segments_conf.conf rescue nil
init_conf["segments"] = nil if init_conf["segments"] && init_conf["segments"].empty?

cancel_change_segments if segments_conf.cancel

# Create or update network configuration scripts for a segment.
#
# @param segment [Hash] a hash representing a network segment, including its name and ports.
# @param init_conf [Hash] the initial configuration data.
def create_or_update_network_scripts(segment, init_conf)
logger = Logger.new(STDOUT)
logger.info("Starting update for segment: #{segment['name']}")
return logger.warn("No ports to configure for segment #{segment['name']}. Skipping configuration.") if segment["ports"].empty?

manage_network_interfaces(init_conf["segments"])
write_network_config_files(segment)
end

# Manage network interfaces by deleting unnecessary configuration files.
#
# @param segments [Array<Hash>] an array of hashes representing network segments.
def manage_network_interfaces(segments)
files_to_delete = find_files_to_delete(segments)
delete_network_interfaces(files_to_delete)
end

# Find network configuration files to delete based on the current segments.
#
# @param segments [Array<Hash>] an array of hashes representing network segments.
# @return [Array<String>] an array of file paths to delete.
def find_files_to_delete(segments)
files_to_delete = []
list_net_conf = Dir.entries("/etc/sysconfig/network-scripts/").select { |f| f.start_with?("ifcfg-b") && !File.directory?(f) }

list_net_conf.each do |netconf|
bridge = netconf.gsub("ifcfg-", "")

if segments.nil? || segments.none? { |s| s['name'] == bridge }
files_to_delete.push("/etc/sysconfig/network-scripts/#{netconf}")
bridge_interfaces = `grep -rnwl '/etc/sysconfig/network-scripts' -e 'BRIDGE="#{bridge}"'`.split("\n")
files_to_delete += bridge_interfaces
end
end

files_to_delete.uniq
end

# Delete network interfaces by removing their configuration files and stopping them.
#
# @param files_to_delete [Array<String>] an array of file paths to delete.
def delete_network_interfaces(files_to_delete)
files_to_delete.each do |iface_path_file|
iface = iface_path_file.split("/").last.gsub("ifcfg-", "") # Extract interface name from file name
puts "Stopping dev #{iface} .."
system("ip link set dev #{iface} down") # Deactivate the interface
if iface.start_with?("b")
puts "Deleting dev bridge #{iface}"
system("brctl delbr #{iface}")
end
File.delete(iface_path_file) if File.exist?(iface_path_file)
end
end

# Write network configuration files for a given segment.
#
# @param segment [Hash] a hash representing a network segment, including its name and ports.
def write_network_config_files(segment)
logger = Logger.new(STDOUT)
begin
segment_file = "/etc/sysconfig/network-scripts/ifcfg-#{segment['name']}"
File.open(segment_file, 'w') do |f|
f.puts "DEVICE=#{segment['name']}"
f.puts "TYPE=Bridge"
f.puts "BOOTPROTO=none"
f.puts "ONBOOT=yes"
f.puts "IPV6_AUTOCONF=no"
f.puts "IPV6INIT=no"
f.puts "DELAY=0"
f.puts "STP=off"
end
logger.info("Segment file created: #{segment_file}")

segment["ports"].each do |iface|
iface_file = "/etc/sysconfig/network-scripts/ifcfg-#{iface}"
File.open(iface_file, 'w') do |f|
f.puts "DEVICE=\"#{iface}\""
f.puts "BRIDGE=\"#{segment['name']}\""
f.puts "TYPE=Ethernet"
f.puts "BOOTPROTO=none"
f.puts "NM_CONTROLLED=\"no\""
f.puts "ONBOOT=\"yes\""
f.puts "IPV6_AUTOCONF=no"
f.puts "IPV6INIT=no"
f.puts "DELAY=0"
f.puts "STP=off"
end
logger.info("Interface file created: #{iface_file}")
end

# Restart network to apply changes
system('pkill dhclient &> /dev/null')
system('service network restart &> /dev/null')
sleep 10
logger.info("Network restart completed.")
rescue => e
logger.error("Error during segment configuration: #{e.message}")
end
end

manage_network_interfaces(init_conf["segments"])

unless init_conf["segments"].nil?
init_conf["segments"].each do |segment|
create_or_update_network_scripts(segment, init_conf)
end
end

save_config(CONFFILE, init_conf)
init_conf = load_config(CONFFILE)
system('pkill dhclient &> /dev/null')
system('service network restart &> /dev/null')
sleep 10

system('ohai -d /etc/chef/ohai/plugins/ redborder')

puts "Executing rb_wakeup_chef"
system('rb_wake_up.sh')

0 comments on commit 201f397

Please sign in to comment.