MT#16719 Support cloning of host sections

When setting up carrier environments we have to deal
with many similar nodes, often involving >10 proxy pairs.
By default we create prx01a and prx01b sections only.
Provide --clone-from=<HOST> --clone-to=<HOST> options
as convenience helpers so the operator can clone a
specific host definition and just needs to adapt IP
addresses accordingly afterwards.

Use example to clone the prox01a host definition
to prox02a, prox03a,.... up to prox10a:

  for host in {02..10} ; do
    ngcp-network --clone-from=prx01a --clone-to=prx${host}a
  done

If the peer setting (as used in carrier environments) is
present in the source host config (--clone-from=...) then
we automatically set the peer for the destination, like:

| # ngcp-network --clone-from=prx01a --clone-to=prx01b
| Setting peer of host 'prx01b' to 'prx01a'
| Finished cloning host section 'prx01a' to 'prx01b'.
| Please do not forget to manually adjust '/etc/ngcp-config/network.yml'!

and:

| # ngcp-network --clone-from=prx01a --clone-to=prx04a
| Setting peer of host 'prx04a' to 'prx04b'
| Finished cloning host section 'prx01a' to 'prx04a'.
| Please do not forget to manually adjust '/etc/ngcp-config/network.yml'!

Change-Id: I6c30a2ce58dd8bc66247cfdd0028c18736173e99
changes/47/4747/8
Michael Prokop 10 years ago
parent 4fd512261b
commit 14dbc9d0b8

@ -15,6 +15,7 @@ use Net::Netmask;
use Pod::Usage;
use Regexp::IPv6 qw($IPv6_re);
use Socket;
use Storable qw(dclone);
use Sys::Hostname;
use YAML::Tiny;
@ -33,6 +34,8 @@ my $bond_miimon;
my $bond_mode;
my $bond_slaves;
my $broadcast;
my $clone_from;
my $clone_to;
my $dbnode;
my @dns_nameservers;
my $gateway;
@ -65,6 +68,8 @@ GetOptions(
'bond-mode=s' => \$bond_mode,
'bond-slaves=s' => \$bond_slaves,
'broadcast=s' => \$broadcast,
'clone-from=s' => \$clone_from,
'clone-to=s' => \$clone_to,
'dbnode:i' => \$dbnode,
'dns=s' => \@dns_nameservers,
'gateway=s' => \$gateway,
@ -128,7 +133,8 @@ if ($ip_v6) {
}
foreach my $opt (
$bond_miimon, $bond_mode, $broadcast, $dbnode, @dns_nameservers,
$bond_miimon, $bond_mode, $broadcast, $clone_from,
$clone_to, $dbnode, @dns_nameservers,
$gateway, @set_interface, $host, $hwaddr,
$internal_iface, $ip, $ip_v6, $move_from,
$move_to, $netmask, $peer, @remove_host,
@ -390,6 +396,58 @@ sub set_dbnode {
return;
}
sub clone_settings {
my $from = shift;
my $to = shift;
if ( defined $from && !defined $to ) {
croak '--clone-from option must be used with --clone-to option together';
}
if ( !defined $from && defined $to ) {
croak '--clone-to option must be used with --clone-from option together';
}
# ha, nothing to do for us
if ( !defined $from && !defined $to ) {
return;
}
logger("clone from = $from");
logger("clone to = $to");
if ( !defined $yaml->[0]->{hosts}->{$from} ) {
croak "Host '$from' doesn\'t exist, refusing to clone settings.";
}
$yaml->[0]->{hosts}->{$to} = dclone($yaml->[0]->{hosts}->{$from});
# adjust peer on-the-fly to prevent user mistakes
if ( defined $yaml->[0]->{hosts}->{$from}->{peer} ) {
if ( $to !~ /[ab]$/ ) {
carp "Target host $from not ending with 'a' or 'b', skipping automatic peer config.";
} else {
logger('Target host matching ".*[ab]$" pattern');
my $other_node;
if ( $to =~ /a$/ ) {
$other_node = $to =~ s/a$/b/r;
} else {
$other_node = $to =~ s/b$/a/r;
}
print "Setting peer for host '$to' to '$other_node'.\n";
$yaml->[0]->{hosts}->{$to}->{peer} = $other_node;
}
}
print "Finished cloning host section '$from' to '$to'.\n" or croak 'Output error';
print "Please do not forget to manually adjust '$outputfile'!\n" or croak 'Output error';
return;
}
sub move_settings {
my $from = shift;
my $to = shift;
@ -503,6 +561,7 @@ if ( defined $dbnode && ( !defined $move_from || !defined $move_to ) )
move_settings( $move_from, $move_to );
clone_settings ( $clone_from, $clone_to );
open my $fh, '>', "$outputfile"
or croak "Could not open $outputfile for writing";
@ -545,6 +604,23 @@ Set bond_slaves configuration to specified argument.
Set broadcast configuration to specified argument.
=item B<--clone-from=<HOST>>
Clone specified HOST section, using specified HOST setting as its source.
Please do not forget to manually adjust the resulting configuration file, no
further checks like duplicated IPs are performed. Needs to be used in
combination with the '--clone-to=<HOST>' option.
This option is useful especially in carrier setups with plenty of similar
web/db/proxy/.... systems, where the host definition of a host like 'prx01a'
should be used as base for another host 'prx02a'. Usage example:
'--clone-from=prx01a --clone-to=prx02a'
=item B<--clone-to=<HOST>>
Clone specified HOST section, using specified HOST setting as its destination.
Refer to '--clone-from=<HOST>' for further information.
=item B<--dbnode=<ID>>
Set dbnode configuration to specified number argument. If no value
@ -705,6 +781,7 @@ Usage examples useful especially on sip:provider PRO systems:
Usage examples useful especially on sip:carrier systems:
ngcp-network --host=proxy2 --set-interface=eth0 --ip=192.168.10.42 --netmask=255.255.255.0
ngcp-network --clone-from=prx01a --clone-to=prx02a
=head1 REQUIRED ARGUMENTS

@ -1,4 +1,5 @@
requires 'Carp';
requires 'Data::Clone';
requires 'Data::Validate::IP';
requires 'Getopt::Long';
requires 'IO::Interface';

Loading…
Cancel
Save