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

creating images from base works now

parent b76343de
<domain type='kvm'>
<name>xenial</name>
<uuid>1805fb4f-ca45-a946-efbf-94124e760400</uuid>
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc-i440fx-trusty'>hvm</type>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/kvm-spice</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/jessie.img'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
<boot order='1'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/ubuntu-16.04-desktop-i386.iso'/>
<target dev='hdc' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='1' target='0' unit='0'/>
<boot order='2'/>
</disk>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<interface type='network'>
<mac address='52:54:00:a7:49:36'/>
<source network='default'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='pty'>
<target port='0'/>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='spice' autoport='yes' listen='10.1.36.68'>
<listen type='address' address='10.1.36.68'/>
</graphics>
<sound model='ich6'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</memballoon>
</devices>
</domain>
<volume type='file'>
<name>__name__.img</name>
<key>/var/lib/libvirt/images/__name__.img</key>
<source>
</source>
<capacity unit='bytes'>6442450944</capacity>
<allocation unit='bytes'>5395775488</allocation>
<target>
<path>/var/lib/libvirt/images/__name__.img</path>
<format type='qcow2'/>
<permissions>
<mode>0600</mode>
<owner>0</owner>
<group>0</group>
</permissions>
<timestamps>
<atime>1461924534.956408726</atime>
<mtime>1461672183.623804946</mtime>
<ctime>1461672193.267892180</ctime>
</timestamps>
</target>
</volume>
......@@ -72,4 +72,25 @@ sub search_domain {
return $domain if $domain;
}
}
sub remove_volume {
my $self = shift;
my $file = shift;
my ($name) = $file =~ m{.*/(.*)};
my $removed = 0;
for my $vm (@{$self->vm}) {
my $vol = $vm->search_volume($name);
next if !$vol;
$vol->delete();
$removed++;
}
if (!$removed && -e $file ) {
warn "volume $file not found. removing file $file.\n";
unlink $file or die "$! $file";
}
}
1;
......@@ -8,26 +8,46 @@ use Moose::Role;
requires 'name';
requires 'remove';
requires 'display';
has 'domain' => (
isa => 'Object'
,is => 'ro'
);
##################################################################################3
#
sub id {
return $_[0]->_data('id');
}
sub file_base_img {
return $_[0]->_data('file_base_img');
}
##################################################################################
sub _data {
my $self = shift;
my $field = shift or confess "Missing field name";
return $self->{_data}->{$field} if exists $self->{_data}->{$field};
$self->_load_sql_data();
return $self->{id} if exists $self->{id};
return $self->{_data}->{$field};
}
my $sth = $self->connector->dbh->prepare("SELECT id FROM domains "
sub _load_sql_data {
my $self = shift;
my $sth = $self->connector->dbh->prepare("SELECT * FROM domains "
." WHERE name=?"
);
$sth->execute($self->name);
my ($id) = $sth->fetchrow;
my $data = $sth->fetchrow_hashref;
$sth->finish;
$self->{_data} = $data;
$self->{id} = $id;
return $id;
return $data;
}
sub open {
......
......@@ -3,6 +3,7 @@ package Ravada::Domain::KVM;
use warnings;
use strict;
use Data::Dumper;
use IPC::Run3 qw(run3);
use Moose;
use XML::LibXML;
......@@ -93,7 +94,8 @@ sub vol_remove {
my $file = shift;
my ($name) = $file =~ m{.*/(.*)} if $file =~ m{/};
my $vol = $self->storage->get_volume_by_name($name);
my $vol;
eval { $vol = $self->storage->get_volume_by_name($name) };
if (!$vol) {
warn "WARNING: I can't find volumne $name\n";
return;
......@@ -106,13 +108,23 @@ sub remove {
$self->domain->shutdown if $self->domain->is_active();
$self->_wait_down();
$self->vol_remove($self->file_base_img) if $self->file_base_img();
$self->domain->destroy if $self->domain->is_active();
$self->remove_disks();
$self->remove_file_image();
$self->domain->undefine();
}
sub remove_file_image {
my $self = shift;
my $file = $self->file_base_img;
$self->vol_remove($file) if $file;
unlink $file or die "$! $file" if -e $file;
}
sub _disk_device {
my $self = shift;
my $doc = XML::LibXML->load_xml(string => $self->domain->get_xml_description)
......@@ -179,4 +191,25 @@ sub prepare_base {
#update domains set is_base='y' , img = $file_qcow
$self->_prepare_base_db($file_qcow);
}
=head2 display
Returns the display URI
=cut
sub display {
my $self = shift;
return $self->{_display} if exists $self->{_display};
my $xml = XML::LibXML->load_xml(string => $self->domain->get_xml_description);
my ($graph) = $xml->findnodes('/domain/devices/graphics')
or die "ERROR: I can't find graphic";
my ($type) = $graph->getAttribute('type');
my ($port) = $graph->getAttribute('port');
my ($address) = $graph->getAttribute('listen');
return "$type://$address:$port";
}
1;
......@@ -178,6 +178,23 @@ sub create_volume {
}
=head2 search_volume
Searches a volume
my $vol =$vm->search_volume($name);
=cut
sub search_volume {
my $self = shift;
my $name = shift or confess "Missing volume name";
my $vol;
eval { $vol = $self->storage_pool->get_volume_by_name($name) };
return $vol;
}
sub _domain_create_from_iso {
my $self = shift;
my %args = @_;
......@@ -244,8 +261,6 @@ sub _create_disk_qcow2 {
exit;
}
warn " qcow created\t\$?=$?\n";
return $file_out;
}
......@@ -277,7 +292,7 @@ sub _domain_create_from_base {
my $vm = $self->vm;
my $storage = $self->storage_pool;
my $xml = $base->domain->get_xml_description();
my $xml = XML::LibXML->load_xml(string => $base->domain->get_xml_description());
my $device_disk = $self->_create_disk($base, $args{name});
# _xml_modify_cdrom($xml, $device_cdrom);
......@@ -285,8 +300,8 @@ sub _domain_create_from_base {
$node_name->setData($args{name});
_xml_modify_disk($xml, $device_disk);
_xml_modify_mac($xml);
_xml_modify_uuid($xml);
$self->_xml_modify_mac($xml);
$self->_xml_modify_uuid($xml);
_xml_modify_spice_port($xml);
_xml_modify_video($xml);
......@@ -530,7 +545,7 @@ sub _new_uuid {
sub _xml_modify_mac {
my $self = shift;
my $doc = shift;
my $doc = shift or confess "Missing XML doc";
my ($if_mac) = $doc->findnodes('/domain/devices/interface/mac')
or exit;
......
......@@ -9,11 +9,19 @@ CREATE TABLE `iso_images` (
);
INSERT INTO iso_images
(name,description,arch,xml,xml_volume,url)
VALUES('Debian Jessie 32 bits netinst'
,'Debian 8.4.0 Jessie 32 bits (netsinst)'
,'i386'
,'jessie-i386.xml'
,'jessie-volume.xml'
,'http://cdimage.debian.org/debian-cd/8.4.0/i386/iso-cd/debian-8.4.0-i386-netinst.iso');
INSERT INTO iso_images
(name,description,arch,xml,xml_volume,url)
VALUES('Ubuntu Trusty 32 bits','Ubuntu 14.04 LTS Trusty 32 bits'
,'i386'
,'trusty-i386.xml'
,'trusty-volume.xml'
,'http://localhost:/ubuntu-16.04-desktop-i386.iso');
,'http://releases.ubuntu.com/16.04/ubuntu-16.04-desktop-i386.iso');
INSERT INTO iso_images
(name,description,arch,xml,xml_volume,url)
......
......@@ -2,6 +2,7 @@ use warnings;
use strict;
use IPC::Run3;
use POSIX ":sys_wait_h";
use Test::More;
use Test::SQL::Data;
......@@ -11,6 +12,10 @@ use_ok('Ravada::Domain::KVM');
my $test = Test::SQL::Data->new( config => 't/etc/ravada.conf');
my $ravada = Ravada->new( connector => $test->connector);
my ($DOMAIN_NAME) = $0 =~ m{.*/(.*)\.};
my $DOMAIN_NAME_SON=$DOMAIN_NAME."_son";
sub test_vm_kvm {
my $vm = $ravada->vm->[0];
ok($vm,"No vm found") or exit;
......@@ -28,22 +33,31 @@ sub test_remove_domain {
if ($domain) {
diag("Removing domain $name");
$domain->remove();
eval { $domain->remove() };
ok(!$@ , "Error removing domain $name : $@") or exit;
ok(! -e $domain->file_base_img ,"Image file was not removed "
. $domain->file_base_img )
if $domain->file_base_img;
}
$domain = $ravada->search_domain($name);
die "I can't remove old domain $name"
if $domain;
ok(!$domain, "I can't remove old domain $name") or exit;
}
sub test_new_domain_from_iso {
my ($name) = $0 =~ m{.*/(.*)\.};
$name .="_base";
my $name = $DOMAIN_NAME;
test_remove_domain($name);
my $domain = $ravada->create_domain(name => $name, id_iso => 1);
ok($domain,"Domain not created");
diag("Creating new domain $name from iso");
my $domain;
eval { $domain = $ravada->create_domain(name => $name, id_iso => 1) };
ok(!$@,"Domain $name not created: $@");
ok($domain,"Domain not created") or return;
my $exp_ref= 'Ravada::Domain::KVM';
ok(ref $domain eq $exp_ref, "Expecting $exp_ref , got ".ref($domain))
if $domain;
......@@ -76,9 +90,10 @@ sub test_prepare_base {
sub test_new_domain_from_base {
my $base = shift;
my ($name) = $0 =~ m{.*/(.*)\.};
$name .="_son";
my $name = $DOMAIN_NAME_SON;
test_remove_domain($name);
diag("Creating domain $name from base ");
my $domain = $ravada->create_domain(name => $name, id_base => $base->id);
ok($domain,"Domain not created");
my $exp_ref= 'Ravada::Domain::KVM';
......@@ -96,19 +111,71 @@ sub test_new_domain_from_base {
ok($row->{name} && $row->{name} eq $domain->name,"I can't find the domain at the db");
$sth->finish;
SKIP: {
#TODO: that could be done
skip("No remote-viewer",1) if 1 || ! -e "/usr/bin/remote-viewer";
test_spawn_viewer($domain);
}
return $domain;
}
sub test_spawn_viewer {
my $domain = shift;
my $pid = fork();
die "Cannot fork" if !defined $pid;
if ($pid == 0) {
my $uri = $domain->display;
my @cmd = ('remote-viewer',$uri);
my ($in,$out,$err);
run3(\@cmd,\$in,\$out,\$err);
ok(!$?,"Error $? running @cmd");
} else {
sleep 5;
$domain->domain->shutdown;
sleep 5;
$domain->domain->destroy;
exit;
}
waitpid(-1, WNOHANG);
}
sub remove_old_volumes {
my $name = "$DOMAIN_NAME_SON.qcow2";
my $file = "/var/lib/libvirt/images/$name";
remove_volume($file);
remove_volume("/var/lib/libvirt/images/$DOMAIN_NAME.img");
}
sub remove_volume {
my $file = shift;
return if !-e $file;
diag("removing old $file");
$ravada->remove_volume($file);
ok(! -e $file,"file $file not removed" );
}
################################################################
test_vm_kvm();
test_remove_domain($DOMAIN_NAME_SON);
remove_old_volumes();
my $domain = test_new_domain_from_iso();
if (ok($domain,"test domain not created")) {
test_prepare_base($domain);
test_new_domain_from_base($domain);
my $domain_son = test_new_domain_from_base($domain);
test_remove_domain($domain_son->name);
test_remove_domain($domain->name);
}
......
No preview for this file type
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