Skip to content

Commit

Permalink
Multiple HW addresses per netdev & NIC bonding
Browse files Browse the repository at this point in the history
* Multiple hw addresses can be set by providing multiple --hwaddr arguments
  or giving a comma separated list of hw addresses
* In the same way bonding devices can be set with --bonddevs
* Bonding mode can be set with --bondmode

Example:
  wwsh node set node1 --netdev bond0 \
    --hwaddr aa:bb:cc:dd:ee:01,aa:bb:cc:dd:ee:02 \
    --bonddevs eth0,eth1 \
    --bondmode 802.3ad

Changed interfaces:

* Warewulf::Node::update_netdev_member()

  Changed order of 'validator' and 'new_values' parameters
  new_values can now be a list

  The function is not used anywhere else.
  This is now consistent with the order that is also used in Object::prop().
  • Loading branch information
beinvisible authored and bensallen committed May 14, 2019
1 parent 8042caa commit 2d57963
Show file tree
Hide file tree
Showing 6 changed files with 477 additions and 173 deletions.
85 changes: 75 additions & 10 deletions common/lib/Warewulf/Module/Cli/Node.pm
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ help()
$h .= " -N, --network Set network address of netdev\n";
$h .= " -G, --gateway Set gateway of given netdev\n";
$h .= " -H, --hwaddr Set hardware/MAC address\n";
$h .= " -b, --bonddevs Set bonding slave devices\n";
$h .= " -B, --bondmode Set bonding mode\n";
$h .= " -f, --fqdn Set FQDN of given netdev\n";
$h .= " -m, --mtu Set MTU of given netdev\n";
$h .= " -p, --hwprefix Specify a prefix for hardware/MAC address of a given netdev\n";
Expand Down Expand Up @@ -178,7 +180,9 @@ exec()
my $opt_lookup = "name";
my $opt_netdev = $config_defaults->get("netdev");
my $opt_netrename;
my $opt_hwaddr;
my @opt_hwaddrs;
my @opt_bonddevs;
my $opt_bondmode;
my $opt_hwprefix;
my $opt_ipaddr;
my $opt_netmask;
Expand Down Expand Up @@ -219,7 +223,7 @@ exec()
'D|netdev=s' => \$opt_netdev,
'netdel' => \$opt_devremove,
'netrename=s' => \$opt_netrename,
'H|hwaddr=s' => \$opt_hwaddr,
'H|hwaddr=s' => \@opt_hwaddrs,
'p|hwprefix=s' => \$opt_hwprefix,
'I|ipaddr=s' => \$opt_ipaddr,
'N|network=s' => \$opt_network,
Expand All @@ -230,6 +234,8 @@ exec()
'a|arch=s' => \$opt_arch,
'f|fqdn=s' => \$opt_fqdn,
'm|mtu=s' => \$opt_mtu,
'b|bonddevs=s' => \@opt_bonddevs,
'B|bondmode=s' => \$opt_bondmode,
'd|domain=s' => \$opt_domain,
'l|lookup=s' => \$opt_lookup,
'e|enabled=s' => \$opt_enabled,
Expand Down Expand Up @@ -341,14 +347,16 @@ exec()
printf("%15s: %-16s = %s\n", $nodename, "GROUPS", join(",", $o->groups()) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "ENABLED", ($o->enabled()) ? "TRUE" : "FALSE");
foreach my $devname (sort($o->netdevs_list())) {
printf("%15s: %-16s = %s\n", $nodename, "$devname.HWADDR", $o->hwaddr($devname) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.HWADDR", $o->hwaddr($devname) ? join(',', $o->hwaddr($devname)) : "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.HWPREFIX", $o->hwprefix($devname) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.IPADDR", $o->ipaddr($devname) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.NETMASK", $o->netmask($devname) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.NETWORK", $o->network($devname) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.GATEWAY", $o->gateway($devname) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.MTU", $o->mtu($devname) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.FQDN", $o->fqdn($devname) || "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.BONDDEVS", $o->bonddevs($devname) ? join(',', $o->bonddevs($devname)) : "UNDEF");
printf("%15s: %-16s = %s\n", $nodename, "$devname.BONDMODE", $o->bondmode($devname) || "UNDEF");
}
$return_count++;
}
Expand Down Expand Up @@ -398,10 +406,15 @@ exec()
push(@changes, sprintf("%8s: %-20s = %s\n", "SET", "$opt_netdev.NAME", $opt_netrename));

} else {
if ($opt_hwaddr) {
if (@opt_hwaddrs) {
if ($objSet->count() == 1) {
$opt_hwaddr = lc($opt_hwaddr);
if ($opt_hwaddr =~ /^((?:[0-9a-f]{2}:){5,7}[0-9a-f]{2})$/) {
@opt_hwaddrs = split(/,/, join(',', @opt_hwaddrs));
@opt_hwaddrs = map { lc $_ } @opt_hwaddrs;

if (grep { $_ !~ /^((?:[0-9a-f]{2}:){5,7}[0-9a-f]{2}|undef)$/ } @opt_hwaddrs) {
&eprint("Option 'hwaddrs' has invalid characters\n");
}
else {
my $show_changes;
foreach my $o ($objSet->get_list()) {
my $nodename = $o->name();
Expand All @@ -414,15 +427,13 @@ exec()
return undef;
}
}
$o->hwaddr($opt_netdev, $1);
$o->hwaddr($opt_netdev, @opt_hwaddrs);
$persist_count++;
$show_changes = 1;
}
if ($show_changes) {
push(@changes, sprintf("%8s: %-20s = %s\n", "SET", "$opt_netdev.HWADDR", $opt_hwaddr));
push(@changes, sprintf("%8s: %-20s = %s\n", "SET", "$opt_netdev.HWADDR", join(',', @opt_hwaddrs)));
}
} else {
&eprint("Option 'hwaddr' has invalid characters\n");
}
} else {
&eprint("Can not set HWADDR on more then 1 node!\n");
Expand Down Expand Up @@ -606,6 +617,60 @@ exec()
&eprint("Option 'mtu' has invalid characters\n");
}
}
if (@opt_bonddevs) {
@opt_bonddevs = split(/,/, join(',', @opt_bonddevs));

if (grep { $_ !~ /^([a-z0-9]+)$/ } @opt_bonddevs) {
&eprint("Option 'bonddevs' has invalid characters\n");
}
else {
my $show_changes;
foreach my $o ($objSet->get_list()) {
my $nodename = $o->name();
if (! $opt_netdev) {
my @devs = $o->netdevs_list();
if (scalar(@devs) == 1) {
$opt_netdev = shift(@devs);
} else {
&eprint("Option --bonddevs requires the --netdev option for: $nodename\n");
return undef;
}
}
$o->bonddevs($opt_netdev, @opt_bonddevs);
$persist_count++;
$show_changes = 1;
}
if ($show_changes) {
push(@changes, sprintf("%8s: %-20s = %s\n", "SET", "$opt_netdev.BONDDEVS", join(',', @opt_bonddevs)));
}
}
}
if ($opt_bondmode) {
if ($opt_bondmode =~ /^(.+)$/) {
my $show_changes;
foreach my $o ($objSet->get_list()) {
my $nodename = $o->name();
if (! $opt_netdev) {
my @devs = $o->netdevs_list();
if (scalar(@devs) == 1) {
$opt_netdev = shift(@devs);
} else {
&eprint("Option --bondmode requires the --netdev option for: $nodename\n");
return undef;
}
}
$o->bondmode($opt_netdev, $1);
$persist_count++;
$show_changes = 1;
}
if ($show_changes) {
push(@changes, sprintf("%8s: %-20s = %s\n", "SET", "$opt_netdev.BONDMODE", $opt_bondmode));
}
}
else {
&eprint("Option 'bondmode' has invalid characters\n");
}
}
}

if ($opt_name) {
Expand Down
114 changes: 75 additions & 39 deletions common/lib/Warewulf/Node.pm
Original file line number Diff line number Diff line change
Expand Up @@ -445,14 +445,14 @@ netdel()
$netdev = $self->netdevs($devname);
$nodename = $self->nodename() || "UNDEF";
if ($netdev) {
my $hwaddr = $netdev->get("hwaddr");
my @hwaddrs = $netdev->get("hwaddr");
my $ipaddr = $netdev->get("ipaddr");
my $hwprefix = $netdev->get("hwprefix");

&dprint("Object $nodename del netdev $devname\n");
$self->netdevs()->del($netdev);
if ($hwaddr) {
$self->del("_hwaddr", $hwaddr);
if (@hwaddrs) {
$self->del("_hwaddr", @hwaddrs);
}
if ($ipaddr) {
$self->del("_ipaddr", $ipaddr);
Expand Down Expand Up @@ -532,12 +532,11 @@ Get or set the hwaddr for the network device named I<$devname>.
sub
hwaddr()
{
my ($self, $devname, $new_hwaddr) = @_;
my ($self, $devname, @new_hwaddr) = @_;

return $self->update_netdev_member($devname, "hwaddr", "_hwaddr",
(((scalar(@_) >= 3) && (!defined($new_hwaddr))) ? ("__UNDEF")
: ((defined($new_hwaddr)) ? (lc($new_hwaddr)) : (undef))),
qr/^((?:[0-9a-f]{2}:){5,7}[0-9a-f]{2})$/);
qr/^((?:[0-9a-f]{2}:){5,7}[0-9a-f]{2})$/,
((scalar(@_) >= 3) && (!defined $new_hwaddr[0])) ? ("__UNDEF") : (@new_hwaddr));
}

=item hwprefix_list()
Expand Down Expand Up @@ -566,9 +565,9 @@ hwprefix()
my ($self, $devname, $new_hwprefix) = @_;

return $self->update_netdev_member($devname, "hwprefix", "_hwprefix",
(((scalar(@_) >= 3) && (!defined($new_hwprefix))) ? ("__UNDEF")
: ((defined($new_hwprefix)) ? (lc($new_hwprefix)) : (undef))),
qr/^((?:[0-9a-f]{2}:){11}[0-9a-f]{2})$/);
qr/^((?:[0-9a-f]{2}:){11}[0-9a-f]{2})$/,
((scalar(@_) >= 3) && (!defined($new_hwprefix))) ? ("__UNDEF")
: ((defined($new_hwprefix)) ? (lc($new_hwprefix)) : (undef)));
}

=item ipaddr_list()
Expand Down Expand Up @@ -598,8 +597,8 @@ ipaddr()
my ($self, $devname, $new_ipaddr) = @_;

return $self->update_netdev_member($devname, "ipaddr", "_ipaddr",
(((scalar(@_) >= 3) && (!defined($new_ipaddr))) ? ("__UNDEF") : ($new_ipaddr)),
qr/^(\d+\.\d+\.\d+\.\d+)$/);
qr/^(\d+\.\d+\.\d+\.\d+)$/,
((scalar(@_) >= 3) && (!defined($new_ipaddr))) ? ("__UNDEF") : ($new_ipaddr));
}


Expand All @@ -615,8 +614,8 @@ netmask()
my ($self, $devname, $new_netmask) = @_;

return $self->update_netdev_member($devname, "netmask", "",
(((scalar(@_) >= 3) && (!defined($new_netmask))) ? ("__UNDEF") : ($new_netmask)),
qr/^(\d+\.\d+\.\d+\.\d+)$/);
qr/^(\d+\.\d+\.\d+\.\d+)$/,
((scalar(@_) >= 3) && (!defined($new_netmask))) ? ("__UNDEF") : ($new_netmask));
}


Expand All @@ -632,8 +631,8 @@ network()
my ($self, $devname, $new_network) = @_;

return $self->update_netdev_member($devname, "network", "",
(((scalar(@_) >= 3) && (!defined($new_network))) ? ("__UNDEF") : ($new_network)),
qr/^(\d+\.\d+\.\d+\.\d+)$/);
qr/^(\d+\.\d+\.\d+\.\d+)$/,
((scalar(@_) >= 3) && (!defined($new_network))) ? ("__UNDEF") : ($new_network));
}


Expand All @@ -649,8 +648,8 @@ gateway()
my ($self, $devname, $new_gateway) = @_;

return $self->update_netdev_member($devname, "gateway", "",
(((scalar(@_) >= 3) && (!defined($new_gateway))) ? ("__UNDEF") : ($new_gateway)),
qr/^(\d+\.\d+\.\d+\.\d+|UNDEF|undef)$/);
qr/^(\d+\.\d+\.\d+\.\d+|UNDEF|undef)$/,
((scalar(@_) >= 3) && (!defined($new_gateway))) ? ("__UNDEF") : ($new_gateway));
}


Expand All @@ -666,8 +665,8 @@ fqdn()
my ($self, $devname, $new_fqdn) = @_;

return $self->update_netdev_member($devname, "fqdn", "",
(((scalar(@_) >= 3) && (!defined($new_fqdn))) ? ("__UNDEF") : ($new_fqdn)),
qr/^([a-zA-Z0-9\-\.\_]+)$/);
qr/^([a-zA-Z0-9\-\.\_]+)$/,
((scalar(@_) >= 3) && (!defined($new_fqdn))) ? ("__UNDEF") : ($new_fqdn));
}


Expand All @@ -683,8 +682,40 @@ mtu()
my ($self, $devname, $new_mtu) = @_;

return $self->update_netdev_member($devname, "mtu", "",
(((scalar(@_) >= 3) && (!defined($new_mtu))) ? ("__UNDEF") : ($new_mtu)),
qr/^([0-9]+)$/);
qr/^([0-9]+)$/,
((scalar(@_) >= 3) && (!defined($new_mtu))) ? ("__UNDEF") : ($new_mtu));
}

=item bonddevs($devname, [ $value ])
Get or set the bond devices for the network device named I<$devname>.
=cut

sub
bonddevs()
{
my ($self, $devname, @new_bonddevs) = @_;

return $self->update_netdev_member($devname, "bonddevs", "",
qr/^([a-z0-9]+)$/,
((scalar(@_) >= 3) && (!@new_bonddevs)) ? ("__UNDEF") : (@new_bonddevs));
}

=item bondmode($devname, [ $value ])
Get or set the bonding mode for the network device named I<$devname>.
=cut

sub
bondmode()
{
my ($self, $devname, $new_bondmode) = @_;

return $self->update_netdev_member($devname, "bondmode", "",
qr/^(.+)$/,
((scalar(@_) >= 3) && (!defined($new_bondmode))) ? ("__UNDEF") : ($new_bondmode));
}

=item enabled([$value])
Expand Down Expand Up @@ -753,7 +784,7 @@ validate_netdev_name()
sub
update_netdev_member()
{
my ($self, $devname, $member, $tracker, $new_value, $validator) = @_;
my ($self, $devname, $member, $tracker, $validator, @new_values) = @_;
my ($netdev, $nodename);

$nodename = $self->nodename() || "UNDEF";
Expand All @@ -773,29 +804,34 @@ update_netdev_member()
}

$netdev = $self->netdev_get_add($devname);
if (defined($new_value)) {
my $old_value = $netdev->get($member) || "";
if (@new_values && scalar @new_values && defined $new_values[0]) {
my @old_values = $netdev->get($member);
@old_values = () unless (@old_values);

if ($new_value eq "__UNDEF" || lc($new_value) eq "undef" ) {
$new_value = undef;
&dprint("Removing $nodename.$devname.$member (was \"$old_value\")\n");
if (grep { $_ eq "__UNDEF" || lc($_) eq "undef" } @new_values) {
@new_values = undef;
&dprint("Removing $nodename.$devname.$member (was \"@old_values\")\n");
} else {
if ($new_value =~ $validator) {
$new_value = $1;
} else {
&eprint("Invalid value for $nodename.$devname.$member: \"$new_value\"\n");
return undef;
if ($validator) {
foreach my $new_value (@new_values) {
if ($new_value =~ $validator) {
$new_value = $1;
} else {
&eprint("Invalid value for $nodename.$devname.$member: \"@new_values\"\n");
return undef;
}
}
}
&dprint("Updating object $nodename.$devname.$member: \"$old_value\" -> \"$new_value\"\n");
&dprint("Updating object $nodename.$devname.$member: \"@old_values\" -> \"@new_values\"\n");
}
$netdev->set($member, $new_value);
$netdev->set($member, @new_values);
if ($tracker) {
if ($old_value) {
if (@old_values) {
# Delete the previous member if exists...
$self->del($tracker, $old_value);
$self->del($tracker, @old_values);
}
if (defined($new_value)) {
$self->add($tracker, $new_value);
if (@new_values) {
$self->add($tracker, @new_values);
} else {
return undef;
}
Expand Down
6 changes: 6 additions & 0 deletions provision/initramfs/functions
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ export WWDNS
WWNETDEV=`sed -e '/ wwnetdev=/!d;s/.*wwnetdev=\([^ ]*\).*/\1/' /proc/cmdline`
export WWNETDEV

WWBONDDEVS=`sed -e '/ wwbonddevs=/!d;s/.*wwbonddevs=\([^ ]*\).*/\1/' /proc/cmdline`
export WWBONDDEVS

WWBONDMODE=`sed -e '/ wwbondmode=/!d;s/.*wwbondmode=\([^ ]*\).*/\1/' /proc/cmdline`
export WWBONDMODE

WWMTU=`sed -e '/ wwmtu=/!d;s/.*wwmtu=\([^ ]*\).*/\1/' /proc/cmdline`
export WWMTU

Expand Down
Loading

0 comments on commit 2d57963

Please sign in to comment.