diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index 0b131775..e0eb6bc3 100755 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -886,6 +886,7 @@ sub _set_paths 'tr' => "/usr/bin/tr", usermod => "/usr/sbin/usermod", uuidgen => "/usr/bin/uuidgen", + virsh => "/usr/bin/virsh", }, 'lock' => { database => "/tmp/anvil-tools.database.lock", diff --git a/cgi-bin/home b/cgi-bin/home index cabf2037..63ac68f9 100755 --- a/cgi-bin/home +++ b/cgi-bin/home @@ -178,6 +178,7 @@ sub check_availability $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }}); } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { available => $available }}); return($available); } @@ -742,7 +743,9 @@ sub sanity_check_step2 # Do we have a host name, striker user and password? if (not $anvil->Validate->form_field({name => "hostname", type => "domain_name"})) { - $sane = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0012"}) }}); + $anvil->data->{cgi}{hostname}{alert} = 1; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else @@ -763,8 +766,9 @@ sub sanity_check_step2 # The user name if ((not defined $anvil->data->{cgi}{striker_user}{value}) or (not $anvil->data->{cgi}{striker_user}{value})) { + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0013"}) }}); $anvil->data->{cgi}{striker_user}{alert} = 1; - $sane = 0; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::striker_user::alert" => $anvil->data->{cgi}{striker_user}{alert} }}); } else @@ -785,8 +789,9 @@ sub sanity_check_step2 # The password if ((not defined $anvil->data->{cgi}{striker_password}{value}) or (not $anvil->data->{cgi}{striker_password}{value}) or (length($anvil->data->{cgi}{striker_password}{value}) < 6)) { + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0014"}) }}); $anvil->data->{cgi}{striker_password}{alert} = 1; - $sane = 0; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::striker_password::alert" => $anvil->data->{cgi}{striker_password}{alert} }}); } else @@ -815,9 +820,10 @@ sub sanity_check_step2 $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { ip => $ip }}); if (not $anvil->Validate->is_ipv4({ip => $ip})) { - $anvil->data->{cgi}{dns}{alert} = 1; - $sane = 0; - $dns_ok = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0015"}) }}); + $anvil->data->{cgi}{dns}{alert} = 1; + $sane = 0; + $dns_ok = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, dns_ok => $dns_ok, "cgi::dns::alert" => $anvil->data->{cgi}{dns}{alert} }}); } } @@ -853,8 +859,8 @@ sub sanity_check_step2 my $this_network = $network.$count; my $this_ip_key = $this_network."_ip"; my $this_subnet_key = $this_network."_subnet"; - my $this_iface1_key = $this_network."_iface1_mac"; - my $this_iface2_key = $this_network."_iface2_mac"; + my $this_iface1_key = $this_network."_link1_mac_to_set"; + my $this_iface2_key = $this_network."_link2_mac_to_set"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { count => $count, this_ip_key => $this_ip_key, @@ -867,13 +873,19 @@ sub sanity_check_step2 "cgi::${this_iface2_key}::value" => $anvil->data->{cgi}{$this_iface2_key}{value}, }}); + # This will be used to tell the user which interface has a problem, if one exists. + my $network_key = $network =~ /^bcn/ ? "striker_0018" : "striker_0022"; + my $say_network = $anvil->Words->string({key => $network_key, variables => { number => $count }}); + # Is the IP sane? my $ip_ok = 1; if (not $anvil->Validate->form_field({name => $this_ip_key, type => "ipv4"})) { # Nope - $sane = 0; - $ip_ok = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0016", variables => { network => $say_network}}) }}); + $anvil->data->{cgi}{$this_ip_key}{alert} = 1; + $sane = 0; + $ip_ok = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, ip_ok => $ip_ok }}); } else @@ -894,7 +906,9 @@ sub sanity_check_step2 # What about the subnet? if (not $anvil->Validate->form_field({name => $this_subnet_key, type => "subnet"})) { - $sane = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0016", variables => { network => $say_network }}) }}); + $anvil->data->{cgi}{$this_subnet_key}{alert} = 1; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } elsif ($ip_ok) @@ -922,7 +936,9 @@ sub sanity_check_step2 # Interface 1 must be set if (not $anvil->Validate->form_field({name => $this_iface1_key, type => "mac"})) { - $sane = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0017", variables => { network => $say_network, 'link' => "1" }}) }}); + $anvil->data->{cgi}{$this_iface1_key}{alert} = 1; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else @@ -950,10 +966,11 @@ sub sanity_check_step2 else { # Conflict! Set the alert for this interface and the conflicting one. - my $conflict_key = $anvil->data->{network}{$mac}{set_as}; + my $conflict_key = $anvil->data->{network}{$mac}{set_as}; $anvil->data->{cgi}{$conflict_key}{alert} = 1; $anvil->data->{cgi}{$this_iface1_key}{alert} = 1; - $sane = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0018"}) }}); + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${conflict_key}::alert" => $anvil->data->{cgi}{$conflict_key}{alert}, @@ -967,7 +984,9 @@ sub sanity_check_step2 { if (not $anvil->Validate->form_field({name => $this_iface2_key, type => "mac"})) { - $sane = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0017", variables => { network => $say_network, 'link' => "2" }}) }}); + $anvil->data->{cgi}{$this_iface2_key}{alert} = 1; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else @@ -996,9 +1015,10 @@ sub sanity_check_step2 { # Conflict! Set the alert for this interface and the conflicting one. my $conflict_key = $anvil->data->{network}{$mac}{set_as}; - $anvil->data->{cgi}{$conflict_key}{alert} = 1; - $anvil->data->{cgi}{$this_iface2_key}{alert} = 1; - $sane = 0; + $anvil->data->{cgi}{$conflict_key}{alert} = 1; + $anvil->data->{cgi}{$this_iface2_key}{alert} = 1; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0018"}) }}); + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${conflict_key}::alert" => $anvil->data->{cgi}{$conflict_key}{alert}, @@ -1014,7 +1034,9 @@ sub sanity_check_step2 # if not) if (not $anvil->Validate->form_field({name => "gateway", type => "ipv4", empty_ok => 1})) { - $sane = 0; + $anvil->data->{cgi}{gateway}{alert} = 1; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0019"}) }}); + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else @@ -1049,12 +1071,11 @@ sub sanity_check_step2 } if (not $gateway_interface) { - $anvil->data->{cgi}{gateway}{alert} = 1; - $sane = 0; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::gateway::alert" => $anvil->data->{cgi}{gateway}{alert} }}); - # Explain the problem $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0004"}) }}); + $anvil->data->{cgi}{gateway}{alert} = 1; + $sane = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::gateway::alert" => $anvil->data->{cgi}{gateway}{alert} }}); } } @@ -1103,8 +1124,9 @@ sub sanity_check_step1 # Organization just needs *something* if ((not defined $anvil->data->{cgi}{organization}{value}) or (not $anvil->data->{cgi}{organization}{value})) { + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0020", variables => { field => "striker_0003" }}) }}); $anvil->data->{cgi}{organization}{alert} = 1; - $sane = 0; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::organization::alert" => $anvil->data->{cgi}{organization}{alert} }}); } else @@ -1125,8 +1147,9 @@ sub sanity_check_step1 # The prefix needs to be alphanumeric and be between 1 ~ 5 chatacters. if ((not $anvil->Validate->is_alphanumeric({string => $anvil->data->{cgi}{prefix}{value}})) or (length($anvil->data->{cgi}{prefix}{value}) > 5)) { - $anvil->data->{cgi}{prefix}{alert} = 1; - $sane = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0021"}) }}); + $anvil->data->{cgi}{prefix}{alert} = 1; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::prefix::alert" => $anvil->data->{cgi}{prefix}{alert} }}); } else @@ -1147,7 +1170,9 @@ sub sanity_check_step1 # We can use Validate to check the domain. if (not $anvil->Validate->form_field({name => "domain", type => "domain_name"})) { - $sane = 0; + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0020", variables => { field => "striker_0007" }}) }}); + $anvil->data->{cgi}{domain}{alert} = 1; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else @@ -1168,8 +1193,9 @@ sub sanity_check_step1 # The sequence and IFN count need to be integers. if (not $anvil->Validate->is_positive_integer({number => $anvil->data->{cgi}{sequence}{value}})) { + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0022", variables => { field => "striker_0009" }}) }}); $anvil->data->{cgi}{sequence}{alert} = 1; - $sane = 0; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::sequence::alert" => $anvil->data->{cgi}{sequence}{alert} }}); } else @@ -1189,8 +1215,9 @@ sub sanity_check_step1 if (not $anvil->Validate->is_positive_integer({number => $anvil->data->{cgi}{ifn_count}{value}})) { + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0022", variables => { field => "striker_0011" }}) }}); $anvil->data->{cgi}{ifn_count}{alert} = 1; - $sane = 0; + $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::ifn_count::alert" => $anvil->data->{cgi}{ifn_count}{alert} }}); } @@ -1212,11 +1239,9 @@ sub sanity_check_step1 }}); # Not enough interfaces found. - $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $say_message }}); - - # We're not sane + $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $say_message }}); $anvil->data->{cgi}{ifn_count}{alert} = 1; - $sane = 0; + $sane = 0; } else { @@ -1383,7 +1408,7 @@ sub get_network_details my $xml = XML::Simple->new(); my $data = ""; my $network = ""; - eval { $data = $xml->XMLin($file, KeyAttr => { interface => 'name', key => 'name', ip => 'address' }, ForceArray => [ 'interface', 'key' ]) }; + eval { $data = $xml->XMLin($file, KeyAttr => { interface => 'name', key => 'name', ip => 'address' }, ForceArray => [ 'interface', 'key' ] ) }; if ($@) { chomp $@; @@ -1422,15 +1447,33 @@ sub get_network_details "interfaces::${interface}::state" => $anvil->data->{interfaces}{$interface}{'state'}, }}); } - foreach my $address (sort {$a cmp $b} keys %{$data->{ip}}) + ### TODO: Sort out how to read the XML using the proper KeyAttr to avoid this mess... + # If there is only one IP, the details will be stored directly under the 'ip' key. If two or + # more exist, each ip address will be the key after 'ip'. + if (exists $data->{ip}{address}) { - # {ip}{address}; + my $on = $data->{ip}{on}; + my $subnet = $data->{ip}{subnet}; + my $gateway = $data->{ip}{gateway}; + my $default_gateway = $data->{ip}{default_gateway}; + my $dns = $data->{ip}{dns}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + address => $address, + on => $on, + subnet => $subnet, + gateway => $gateway, + default_gateway => $default_gateway, + dns => $dns, + }}); + $anvil->data->{ip}{$address} = { - on => $data->{ip}{$address}{on}, - subnet => $data->{ip}{$address}{subnet}, - gateway => $data->{ip}{$address}{gateway}, - default_gateway => $data->{ip}{$address}{default_gateway}, - dns => $data->{ip}{$address}{dns}, + on => $on, + subnet => $subnet, + gateway => $gateway, + default_gateway => $default_gateway, + dns => $dns, }; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ip::${address}::on" => $anvil->data->{ip}{$address}{on}, @@ -1440,6 +1483,27 @@ sub get_network_details "ip::${address}::dns" => $anvil->data->{ip}{$address}{dns}, }}); } + else + { + foreach my $address (sort {$a cmp $b} keys %{$data->{ip}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { address => $address }}); + $anvil->data->{ip}{$address} = { + on => $data->{ip}{$address}{on}, + subnet => $data->{ip}{$address}{subnet}, + gateway => $data->{ip}{$address}{gateway}, + default_gateway => $data->{ip}{$address}{default_gateway}, + dns => $data->{ip}{$address}{dns}, + }; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "ip::${address}::on" => $anvil->data->{ip}{$address}{on}, + "ip::${address}::subnet" => $anvil->data->{ip}{$address}{subnet}, + "ip::${address}::gateway" => $anvil->data->{ip}{$address}{gateway}, + "ip::${address}::default_gateway" => $anvil->data->{ip}{$address}{default_gateway}, + "ip::${address}::dns" => $anvil->data->{ip}{$address}{dns}, + }}); + } + } } return(0); diff --git a/rpm/SPECS/anvil.spec b/rpm/SPECS/anvil.spec index dd5e398f..c9725383 100644 --- a/rpm/SPECS/anvil.spec +++ b/rpm/SPECS/anvil.spec @@ -169,6 +169,8 @@ systemctl start httpd.service # Open access for Striker. The database will be opened after initial setup. firewall-cmd --zone=public --add-service=http firewall-cmd --zone=public --add-service=http --permanent +firewall-cmd --zone=public --add-service=postgresql +firewall-cmd --zone=public --add-service=postgresql --permanent %files core %doc README.md notes diff --git a/share/words.xml b/share/words.xml index 54e08d7b..e9dbdf6f 100644 --- a/share/words.xml +++ b/share/words.xml @@ -267,6 +267,7 @@ The database connection error was: + The IP hash key: [#!variable!ip_key!#] does not exist, skipping it. Test @@ -368,6 +369,17 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st Failed to add the target: [#!variable!target!#]:[#!variable!port!#]'s RSA fingerprint to: [#!variable!user!#]'s list of known hosts. There was a problem adding the local machine to the: [#!data!path::configs::anvil.conf!#] file. Please see the log for details. Something went wrong while trying to update the password. The return code was: [#!variable!return_code!#], but '0' was expected. + hostname has to be set to a valid value.]]> + A user name must be set. This is usually 'admin'. + You must set a password. There are no complexity rules, but a long password is strongly recommended. + A DNS entry is bad. One or more IPv4 addresses can be specified, with a comma separating multiple IPs. + The IPv4 address assigned to: [#!variable!network!#] is invalid. + An interface to use in: [#!variable!network!# - Link #!variable!link!#] must be selected. + Network interfaces can only be selected once. + The gateway appears to have an invalid IPv4 address set. + The: [#!variable!field!#] field can't be empty. + The prefix needs to be set, and be between 1 and 5 characters long. + The: [#!variable!field!#] must be a positive integer. Up diff --git a/tools/anvil-configure-striker b/tools/anvil-configure-striker index 8f1f0b99..8f256e3a 100755 --- a/tools/anvil-configure-striker +++ b/tools/anvil-configure-striker @@ -227,16 +227,16 @@ sub reconfigure_network next if not $count; foreach my $network_count (1..$count) { - my $this_network = $network_type.$network_count; - my $link1_key = $this_network."_iface1_mac"; - my $link2_key = $this_network."_iface2_mac"; - my $subnet_key = $this_network."_subnet"; - my $ip_key = $this_network."_ip"; - my $is_gateway = $this_network eq $gateway_interface ? 1 : 0; - my $link1_mac = $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}; - my $link2_mac = $anvil->data->{variables}{form}{config_step2}{$link2_key}{value}; - my $old_link1_iface = $anvil->data->{sys}{mac}{$link1_mac}{iface} ? $anvil->data->{sys}{mac}{$link1_mac}{iface} : ""; - my $old_link2_iface = $anvil->data->{sys}{mac}{$link2_mac}{iface} ? $anvil->data->{sys}{mac}{$link2_mac}{iface} : ""; + my $this_network = $network_type.$network_count; + my $link1_key = $this_network."_link1_mac_to_set"; + my $link2_key = $this_network."_link2_mac_to_set"; + my $subnet_key = $this_network."_subnet"; + my $ip_key = $this_network."_ip"; + my $is_gateway = $this_network eq $gateway_interface ? 1 : 0; + my $link1_mac = $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}; + my $link2_mac = defined $anvil->data->{variables}{form}{config_step2}{$link2_key}{value} ? $anvil->data->{variables}{form}{config_step2}{$link2_key}{value} : ""; + my $old_link1_iface = $anvil->data->{sys}{mac}{$link1_mac}{iface} ? $anvil->data->{sys}{mac}{$link1_mac}{iface} : ""; + my $old_link2_iface = $link2_mac ? $anvil->data->{sys}{mac}{$link2_mac}{iface} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_key => $ip_key, is_gateway => $is_gateway, @@ -251,7 +251,15 @@ sub reconfigure_network }}); # Skip if this doesn't exist or isn't a valid IPv4 address. - next if not exists $anvil->data->{variables}{form}{config_step2}{$ip_key}{value}; + if (not exists $anvil->data->{variables}{form}{config_step2}{$ip_key}{value}) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0176", variables => { ip_key => $ip_key }}); + next; + } + else + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "variables::form::config_step2::${ip_key}::value" => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value} }}); + } if (($anvil->data->{variables}{form}{config_step2}{$ip_key}{value}) and (not $anvil->Validate->is_ipv4({ip => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value}}))) { # Something was set, but it isn't valid. @@ -269,10 +277,11 @@ sub reconfigure_network subnet => $subnet, }}); + # Are we building bonded interfaces? if ($anvil->Validate->is_mac({mac => $link2_mac})) { ### TODO: Handle when bridges exist. Detect when the host is a node and/or have a "use as bridge" option? - # Bonded; Build the configs. + # Yup! Build the configs. my $say_network = ""; my $say_interface = ""; my $interface_prefix = ""; @@ -494,9 +503,111 @@ sub reconfigure_network } elsif ((exists $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}) && ($anvil->Validate->is_mac({mac => $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}}))) { - # Single interface + # Single interface, set it up my $link1_mac = $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { link1_mac => $link1_mac }}); + + my $say_network = ""; + my $say_interface = ""; + my $interface_prefix = ""; + if ($network_type eq "bcn") + { + $say_network = "Back-Channel Network ".$network_count; + $say_interface = "bcn".$network_count; + $interface_prefix = "BCN"; + } + elsif ($network_type eq "sn") + { + $say_network = "Storage Network ".$network_count; + $say_interface = "sn".$network_count; + $interface_prefix = "SN"; + } + elsif ($network_type eq "ifn") + { + $say_network = "Internet-Facing Network ".$network_count; + $say_interface = "ifn".$network_count; + $interface_prefix = "IFN"; + } + my $say_defroute = $is_gateway ? "yes" : "no"; + my $cidr = $anvil->Convert->cidr({subnet => $subnet}); + my $new_link1_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$interface_prefix."_".$network_count."_-_Link_1"; + my $old_link1_file = $new_link1_file; + my $new_link1_iface = $say_interface."_link1"; + if ((exists $anvil->data->{sys}{mac}{$link1_mac}{iface}) && ($anvil->data->{sys}{mac}{$link1_mac}{iface})) + { + $old_link1_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$anvil->data->{sys}{mac}{$link1_mac}{iface}; + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + say_defroute => $say_defroute, + cidr => $cidr, + new_link1_file => $new_link1_file, + old_link1_file => $old_link1_file, + new_link1_iface => $new_link1_iface, + }}); + + # Gather (or create) UUIDs + my $link1_uuid = get_uuid_from_interface_file($anvil, $old_link1_file); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { link1_uuid => $link1_uuid }}); + + my $link1_config = "# $say_network - Link 1\n"; + $link1_config .= "HWADDR=\"".uc($link1_mac)."\"\n"; + $link1_config .= "UUID=\"".$link1_uuid."\"\n"; + $link1_config .= "NAME=\"".$interface_prefix." ".$network_count." - Link 1\"\n"; + $link1_config .= "DEVICE=\"".$new_link1_iface."\"\n"; + $link1_config .= "TYPE=\"Ethernet\"\n"; + $link1_config .= "BOOTPROTO=\"none\"\n"; + $link1_config .= "IPV6INIT=\"no\"\n"; + $link1_config .= "ONBOOT=\"yes\"\n"; + $link1_config .= "IPADDR=\"".$ip."\"\n"; + $link1_config .= $cidr ? "PREFIX=\"".$cidr."\"\n" : "NETMASK=\"".$subnet."\"\n"; + if ($is_gateway) + { + $link1_config .= "GATEWAY=\"".$gateway."\"\n"; + for (my $i = 0; $i < @{$dns}; $i++) + { + $link1_config .= "DNS".($i+1)."=\"".$dns->[$i]."\"\n"; + } + } + $link1_config .= "DEFROUTE=\"".$say_defroute."\"\n"; + $link1_config .= "USERCTL=\"no\"\n"; + $link1_config .= "MTU=\"1500\"\n"; # TODO: Make the MTU user-adjustable + $link1_config .= "NM_CONTROLLED=\"yes\"\n"; + $link1_config .= "ZONE=\"".$say_interface."\""; + + # Backup the existing link1 file, if it exists. + if (-e $old_link1_file) + { + $anvil->Storage->backup({debug => 2, file => $old_link1_file}); + } + + # Write out the link1 config file. + $anvil->Storage->write_file({file => $new_link1_file, body => $link1_config, user => "root", group => "root", mode => "0644", overwrite => 1}); + + if ($old_link1_iface) + { + # Take down and rename the old link 1 interface + #print "Downing: ..... [$old_link1_iface]\n"; + #$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifdown}." ".$old_link1_iface}); + #print "Disconnecting: [$old_link1_iface]\n"; + #$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link1_iface." down"}); + } + if ($old_link1_iface ne $new_link1_iface) + { + # Rename it + #print "Renaming: .... [$old_link1_iface] -> [$new_link1_iface]\n"; + #$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link1_iface." name ".$new_link1_iface}); + + # Unllnk the old one, if it exists. + if (-e $old_link1_file) + { + #print "Deleting: .... [$old_link1_file]\n"; + unlink $old_link1_file; + } + } + + # Drop the new link, too, in case it still has the old config + #print "Downing: ..... [$new_link1_iface]\n"; + #$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifdown}." ".$new_link1_iface}); } else { @@ -507,6 +618,43 @@ sub reconfigure_network } } + # If any virtio bridges exist, remove it/them. + my $start = 0; + my $bridges = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." net-list"}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridges => $bridges }}); + foreach my $line (split/\n/, $bridges) + { + $line = $anvil->Words->clean_spaces({ string => $line }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); + if ($line =~ /^----------/) + { + $start = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start => $start }}); + next; + } + next if not $start; + my $bridge = ($line =~ /(.*?)\s/)[0]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge => $bridge }}); + + $anvil->data->{virsh}{bridge}{$bridge} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "virsh::bridge::$bridge" => $anvil->data->{virsh}{bridge}{$bridge} }}); + } + + foreach my $bridge (sort {$a cmp $b} keys %{$anvil->data->{virsh}{bridge}}) + { + # Destroy (stop) it. + my $destroy = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." net-destroy ".$bridge}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { destroy => $destroy }}); + + # Disable it from auto-start. + my $disable = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." net-autostart ".$bridge." --disable"}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { disable => $disable }}); + + # Undefine (delete) + my $undefine = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." net-undefine ".$bridge}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { undefine => $undefine }}); + } + ### TODO: This isn't working... The route table won't set the IFN as the default route properly and ### the IFN links seem to drop out and not return when trying to fix it. For now, we'll do a ### closing reboot which seems to always comes up OK. diff --git a/tools/anvil-update-states b/tools/anvil-update-states index 76b3a31e..3500d527 100755 --- a/tools/anvil-update-states +++ b/tools/anvil-update-states @@ -3,7 +3,6 @@ # This is the master daemon that manages all periodically run processes on Striker dashboards and Anvil! # nodes. # -# TODO: Make sure to delete interfaces/bonds/bridges that disappear # use strict; use warnings;