Commit c5e5e212 authored by Francesc Guasch's avatar Francesc Guasch
Browse files

wip(volatile): listen in the right interface

issue #1099
parent 2a8de0ab
......@@ -1787,6 +1787,7 @@ sub clone {
return $self->_copy_clone(@_) if $self->id_base();
my $remote_ip = delete $args{remote_ip};
my $request = delete $args{request};
my $memory = delete $args{memory};
......@@ -1803,6 +1804,7 @@ sub clone {
my @args_copy = ();
push @args_copy, ( memory => $memory ) if $memory;
push @args_copy, ( request => $request ) if $request;
push @args_copy, ( remote_ip => $remote_ip) if $remote_ip;
my $vm = $self->_vm;
if ($self->volatile_clones ) {
......@@ -3003,10 +3005,8 @@ sub set_driver_id {
}
sub _listen_ip($self, $remote_ip) {
return ( Ravada::display_ip()
or $self->_vm->public_ip
or $self->_vm->_interface_ip($remote_ip));
}
return $self->_vm->listen_ip($remote_ip);
}
sub remote_ip($self) {
......@@ -3454,6 +3454,7 @@ sub _pre_clone($self,%args) {
my $user = delete $args{user};
my $memory = delete $args{memory};
delete $args{request};
delete $args{remote_ip};
confess "ERROR: Missing clone name " if !$name;
confess "ERROR: Invalid name '$name'" if $name !~ /^[a-z0-9_-]+$/i;
......
......@@ -1604,8 +1604,6 @@ sub _set_spice_ip($self, $set_password, $ip=undef) {
=> $self->domain->get_xml_description);
my @graphics = $doc->findnodes('/domain/devices/graphics');
$ip = $self->_vm->ip() if !defined $ip;
for my $graphics ( $doc->findnodes('/domain/devices/graphics') ) {
next if $self->is_hibernated() || $self->domain->is_active;
......@@ -1619,14 +1617,14 @@ sub _set_spice_ip($self, $set_password, $ip=undef) {
}
$self->_set_spice_password($password);
$graphics->setAttribute('listen' => $ip);
$graphics->setAttribute('listen' => ($ip or $self->_vm->listen_ip));
my $listen;
for my $child ( $graphics->childNodes()) {
$listen = $child if $child->getName() eq 'listen';
}
# we should consider in the future add a new listen if it ain't one
next if !$listen;
$listen->setAttribute('address' => $ip);
$listen->setAttribute('address' => ($ip or $self->_vm->listen_ip));
$self->domain->update_device($graphics);
}
}
......
......@@ -51,7 +51,7 @@ sub display_info {
sub _set_display($self, $remote_ip=undef) {
# my $ip = ($self->_vm->nat_ip or $self->_vm->ip());
my $ip = ( $self->_listen_ip($remote_ip) or $self->_vm->ip );
my $ip = $self->_vm->listen_ip($remote_ip);
my $display="void://$ip:5990/";
my $display_data = { display => $display , type => 'void', ip => $ip, port => 5990 };
$self->_store( display => $display_data );
......
......@@ -77,11 +77,6 @@ has 'host' => (
, default => 'localhost'
);
has 'public_ip' => (
isa => 'Str'
, is => 'rw'
);
has 'default_dir_img' => (
isa => 'String'
, is => 'ro'
......@@ -177,7 +172,10 @@ sub open {
lock_hash(%$row);
confess "ERROR: I can't find VM id=$args{id}" if !$row || !keys %$row;
return $VM{$args{id}} if $VM{$args{id}} && $VM{$args{id}}->name eq $row->{name};
if ( $VM{$args{id}} && $VM{$args{id}}->name eq $row->{name} ) {
my $vm = $VM{$args{id}};
return _clean($vm);
}
my $type = $row->{vm_type};
$type = 'KVM' if $type eq 'qemu';
......@@ -207,10 +205,10 @@ sub BUILD {
my $name = delete $args->{name};
my $store = delete $args->{store};
$store = 1 if !defined $store;
my $public_ip = delete $args->{public_ip};
delete $args->{readonly};
delete $args->{security};
delete $args->{public_ip};
# TODO check if this is needed
delete $args->{connector};
......@@ -227,16 +225,11 @@ sub BUILD {
,vm_type => $self->type
);
$query{name} = $name if $name;
$query{public_ip} = $public_ip if defined $public_ip;
$self->_select_vm_db(%query);
}
$self->id;
$self->public_ip($self->_data('public_ip'))
if defined $self->_data('public_ip')
&& (!defined $self->public_ip
|| $self->public_ip ne $self->_data('public_ip')
);
}
sub _open_type {
......@@ -364,12 +357,13 @@ sub _around_create_domain {
my $orig = shift;
my $self = shift;
my %args = @_;
my $remote_ip = delete $args{remote_ip};
my %args_create = %args;
my $id_owner = delete $args{id_owner} or confess "ERROR: Missing id_owner";
my $owner = Ravada::Auth::SQL->search_by_id($id_owner) or confess "Unknown user id: $id_owner";
my $base;
my $remote_ip = delete $args{remote_ip};
my $volatile = delete $args{volatile};
my $id_base = delete $args{id_base};
my $id_iso = delete $args{id_iso};
......@@ -377,7 +371,7 @@ sub _around_create_domain {
my $name = delete $args{name};
my $swap = delete $args{swap};
# args get deleted but kept on @_ so when we call $self->$orig below are passed
# args get deleted but kept on %args_create so when we call $self->$orig below are passed
delete $args{disk};
delete $args{memory};
delete $args{request};
......@@ -402,9 +396,11 @@ sub _around_create_domain {
confess "ERROR: Base ".$base->name." is private"
if !$owner->is_admin && $base && !$base->is_public();
$self->_pre_create_domain(@_);
$args_create{listen_ip} = $self->listen_ip($remote_ip);
$args_create{spice_password} = $self->_define_spice_password($remote_ip);
$self->_pre_create_domain(%args_create);
my $domain = $self->$orig(@_, volatile => $volatile);
my $domain = $self->$orig(%args_create, volatile => $volatile);
$domain->add_volume_swap( size => $swap ) if $swap;
if ($id_base) {
......@@ -435,6 +431,15 @@ sub _around_create_domain {
return $domain;
}
sub _define_spice_password($self, $remote_ip) {
my $spice_password = Ravada::Utils::random_name(4);
if ($remote_ip) {
my $network = Ravada::Network->new(address => $remote_ip);
$spice_password = undef if !$network->requires_password;
}
return $spice_password;
}
sub _check_duplicate_name($self, $name) {
my $sth = $$CONNECTOR->dbh->prepare("SELECT id,name,vm FROM domains where name=?");
$sth->execute($name);
......@@ -601,6 +606,15 @@ sub _interface_ip($self, $remote_ip=undef) {
return $default_ip;
}
sub listen_ip($self, $remote_ip=undef) {
return $self->_interface_ip($remote_ip) if $remote_ip;
return (Ravada::display_ip()
or $self->public_ip
or $self->ip()
);
}
sub _check_memory {
my $self = shift;
my %args = @_;
......@@ -644,7 +658,7 @@ sub _check_require_base {
delete $args{start};
delete $args{remote_ip};
delete @args{'_vm','name','vm', 'memory','description','id_iso'};
delete @args{'_vm','name','vm', 'memory','description','id_iso','listen_ip','spice_password'};
confess "ERROR: Unknown arguments ".join(",",keys %args)
if keys %args;
......@@ -693,6 +707,7 @@ sub _data($self, $field, $value=undef) {
);
$sth->execute($value, $self->id);
$sth->finish;
return $value;
}
......@@ -712,12 +727,17 @@ sub _data($self, $field, $value=undef) {
sub _timed_data_cache($self) {
return if !$self->{$FIELD_TIMEOUT} || time - $self->{$FIELD_TIMEOUT} < $CACHE_TIMEOUT;
return _clean($self);
}
sub _clean($self) {
my $name = $self->{_data}->{name};
my $id = $self->{_data}->{id};
delete $self->{_data};
delete $self->{$FIELD_TIMEOUT};
$self->{_data}->{name} = $name if $name;
$self->{_data}->{id} = $id if $id;
return $self;
}
sub _do_select_vm_db {
......@@ -768,11 +788,12 @@ sub _insert_vm_db {
my %args = @_;
my $name = ( delete $args{name} or $self->name);
my $host = ( delete $args{hostname} or $self->host );
my $public_ip = ( delete $args{public_ip} or '' );
delete $args{vm_type};
confess "Unknown args ".Dumper(\%args) if keys %args;
eval { $sth->execute($name,$self->type,$host, $self->public_ip) };
eval { $sth->execute($name,$self->type,$host, $public_ip) };
confess $@ if $@;
$sth->finish;
......@@ -1057,6 +1078,10 @@ sub is_enabled($self, $value=undef) {
return $self->enabled($value);
}
sub public_ip($self, $value=undef) {
return $self->_data('public_ip', $value);
}
=head2 remove
Remove the virtual machine manager.
......
......@@ -725,7 +725,8 @@ sub _domain_create_from_iso {
if !$args{$_};
}
my $remove_cpu = delete $args2{remove_cpu};
for (qw(disk swap active request vm memory iso_file id_template volatile)) {
for (qw(disk swap active request vm memory iso_file id_template volatile spice_password
listen_ip)) {
delete $args2{$_};
}
......@@ -807,20 +808,16 @@ sub _domain_create_common {
my $id_owner = delete $args{id_owner} or confess "ERROR: The id_owner is mandatory";
my $is_volatile = delete $args{is_volatile};
my $remote_ip = delete $args{remote_ip};
my $listen_ip = delete $args{listen_ip};
my $spice_password = delete $args{spice_password};
my $user = Ravada::Auth::SQL->search_by_id($id_owner)
or confess "ERROR: User id $id_owner doesn't exist";
my $spice_password = Ravada::Utils::random_name(4);
if ($remote_ip) {
my $network = Ravada::Network->new(address => $remote_ip);
$spice_password = undef if !$network->requires_password;
}
$self->_xml_modify_memory($xml,$args{memory}) if $args{memory};
$self->_xml_modify_network($xml , $args{network}) if $args{network};
$self->_xml_modify_mac($xml);
my $uuid = $self->_xml_modify_uuid($xml);
$self->_xml_modify_spice_port($xml, $spice_password);
$self->_xml_modify_spice_port($xml, $spice_password, $listen_ip);
$self->_fix_pci_slots($xml);
$self->_xml_add_guest_agent($xml);
$self->_xml_clean_machine_type($xml) if !$self->is_local;
......@@ -1514,16 +1511,14 @@ sub _xml_modify_video {
}
sub _xml_modify_spice_port {
my $self = shift;
my $doc = shift or confess "Missing XML doc";
my $password = shift;
sub _xml_modify_spice_port($self, $doc, $password=undef, $listen_ip=$self->listen_ip) {
$listen_ip = $self->listen_ip if !defined $listen_ip;
my ($graph) = $doc->findnodes('/domain/devices/graphics')
or die "ERROR: I can't find graphic";
$graph->setAttribute(type => 'spice');
$graph->setAttribute(autoport => 'yes');
$graph->setAttribute(listen=> $self->ip() );
$graph->setAttribute(listen=> $listen_ip );
$graph->setAttribute(passwd => $password) if $password;
my ($listen) = $doc->findnodes('/domain/devices/graphics/listen');
......@@ -1533,8 +1528,7 @@ sub _xml_modify_spice_port {
}
$listen->setAttribute(type => 'address');
$listen->setAttribute(address => $self->ip());
$listen->setAttribute(address => $listen_ip);
}
sub _xml_modify_uuid {
......
......@@ -360,27 +360,65 @@ sub test_old_machine_req {
sub test_ips {
my $vm = shift;
my $domain = create_domain($vm);
$domain->volatile_clones(1);
my $public_ip = $vm->_data('public_ip');
my $out = `ip -4 -o a`;
my @ip;
my @ips;
for my $line (split /\n/, $out) {
my ($if, $ip) = $line =~ /\s(\w+)\s+inet\s+(\d+\.\d+\.\d+\.\d+)/;
push @ip ,($ip) if $if !~ /^virbr/;
push @ips ,($ip) if $if !~ /^virbr/;
}
for my $ip (@ip) {
$vm->_data('public_ip',$ip);
for my $ip (@ips) {
diag("Testing ip $ip");
$vm->public_ip($ip);
is($vm->_data('public_ip'),$ip);
is($vm->public_ip, $ip);
is($vm->listen_ip, $ip);
my $vm2 = Ravada::VM->open($vm->id);
is($vm2->_data('public_ip'),$ip);
is($vm2->listen_ip, $ip);
is($vm2->public_ip, $ip);
my $domain = create_domain($vm);
if ($vm->type ne 'Void') {
my $xml = $domain->get_xml_base;
my ($listen) = $xml =~ m{listen='(.*)'};
my ($address) = $xml =~ m{listen.*address='(.*)'};
is($listen, $ip);
is($address, $ip);
}
$domain->volatile_clones(1);
my $clone = $domain->clone(name => new_domain_name , user => user_admin);
like($clone->display(user_admin), qr(^spice://$ip));
like($clone->display(user_admin), qr(^\w+://$ip));
$clone->remove(user_admin);
$vm->public_ip('');
is($vm->public_ip,'');
for my $ip2 (@ips) {
my $clone2 = $domain->clone(name => new_domain_name , user => user_admin
,remote_ip => $ip2
);
if ($vm->type ne 'Void') {
my $xml = $clone2->xml_description;
my ($listen) = $xml =~ m{listen='(.*)'};
my ($address) = $xml =~ m{listen.*address='(.*)'};
is($listen, $ip2);
is($address, $ip2);
}
like($clone2->display(user_admin), qr(^\w+://$ip2),$clone->name) or exit;
$clone2->remove(user_admin);
}
$domain->remove(user_admin);
}
$domain->remove(user_admin);
$vm->public_ip($public_ip);
}
######################################################################3
......
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