Commit 3146dca8 authored by Francesc Guasch's avatar Francesc Guasch
Browse files

fix(KVM): unique MAC in all network cards

issue #1294
parent 059b4bc4
......@@ -2489,6 +2489,7 @@ sub _execute {
die "I can't fork" if !defined $pid;
if ( $pid == 0 ) {
srand();
$self->_do_execute_command($sub, $request);
exit;
}
......
......@@ -1963,7 +1963,7 @@ sub _set_controller_network($self, $number, $data) {
my $pci_slot = $self->_new_pci_slot();
my $device = "<interface type='network'>
<mac address='52:54:00:a7:49:71'/>
<mac address='".$self->_vm->_new_mac()."'/>
<source network='default'/>
<model type='$driver'/>
<address type='pci' domain='0x0000' bus='0x00' slot='$pci_slot' function='0x0'/>
......
......@@ -64,6 +64,7 @@ $DIR_XML = "/var/lib/ravada/xml/" if $0 =~ m{^/usr/sbin};
our $FILE_CONFIG_QEMU = "/etc/libvirt/qemu.conf";
our $XML = XML::LibXML->new();
our %USED_MAC;
#-----------
#
......@@ -2041,52 +2042,55 @@ sub _new_uuid {
}
sub _xml_modify_mac {
my $self = shift;
my $doc = shift or confess "Missing XML doc";
my @old_macs;
sub _read_used_macs($self) {
return if keys %USED_MAC;
for my $dom ($self->vm->list_all_domains) {
my $doc;
eval { $doc = $XML->load_xml(string => $dom->get_xml_description()) } ;
next if !$doc;
for my $nic ( $doc->findnodes('/domain/devices/interface/mac')) {
my $nic_mac = $nic->getAttribute('address');
push @old_macs,($nic_mac);
my $nic_mac = lc($nic->getAttribute('address'));
$USED_MAC{$nic_mac}++;
}
}
}
for my $if_mac ($doc->findnodes('/domain/devices/interface/mac') ) {
my $mac = $if_mac->getAttribute('address');
my @macparts0 = split/:/,$mac;
sub _new_mac($self,$mac='52:54:00:a7:49:71') {
my $new_mac;
$self->_read_used_macs();
my @macparts = split/:/,$mac;
$macparts[5] = sprintf"%02X",($$ % 254);
my @tried;
my $foundit;
for ( 1 .. 1000 ) {
for my $cont ( 1 .. 1000 ) {
my @macparts = @macparts0;
my $pos = int(rand(scalar(@macparts)-3))+3;
for ( 0 .. 2 ) {
my $num =sprintf "%02X", rand(0xff);
die "Missing num " if !defined $num;
$macparts[$pos] = $num;
$new_mac = lc(join(":",@macparts));
$pos++;
$pos = 3 if $pos>5;
}
my $new_mac = lc(join(":",@macparts));
push @tried,($new_mac);
last if !grep /^$new_mac$/i,@old_macs && $self->_unique_mac($new_mac);
push @old_macs,($new_mac);
return $new_mac if !$USED_MAC{$new_mac}++ && $self->_unique_mac($new_mac);
}
die "I can't find a new unique mac\n".Dumper(\@tried) if !$foundit;
if ( $self->_unique_mac($new_mac) ) {
}
sub _xml_modify_mac {
my $self = shift;
my $doc = shift or confess "Missing XML doc";
for my $if_mac ($doc->findnodes('/domain/devices/interface/mac') ) {
my $mac = $if_mac->getAttribute('address');
my $new_mac = $self->_new_mac($mac);;
$if_mac->setAttribute(address => $new_mac);
$foundit = 1;
last;
}
}
die "I can't find a new unique mac '$new_mac'\n".Dumper(\@tried) if !$foundit;
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment