From: Alexandre Derumier Date: Tue, 3 Jan 2017 14:03:15 +0000 (+0100) Subject: add targetstorage to vm_start X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=2189246c5c33c73ede6be9dd512acc64b5699653;p=qemu-server.git add targetstorage to vm_start This will create a new drive for each local drive found, and start the vm with this new drives. if targetstorage == 1, we use same sid than original vm disk a nbd server is started in qemu and expose local volumes to network port Signed-off-by: Alexandre Derumier --- diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index d21f3dfc..3e4e7f77 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -1642,6 +1642,11 @@ __PACKAGE__->register_method({ optional => 1, }, machine => get_standard_option('pve-qm-machine'), + targetstorage => { + description => "Target migration storage . (1 = same storeid than original)", + type => 'string', + optional => 1 + } }, }, returns => { @@ -1680,6 +1685,13 @@ __PACKAGE__->register_method({ raise_param_exc({ migration_network => "Only root may use this option." }) if $migration_network && $authuser ne 'root@pam'; + my $targetstorage = extract_param($param, 'targetstorage'); + raise_param_exc({ targetstorage => "Only root may use this option." }) + if $targetstorage && $authuser ne 'root@pam'; + + raise_param_exc({ targetstorage => "targetstorage can only by used with migratedfrom." }) + if $targetstorage && !$migratedfrom; + # read spice ticket from STDIN my $spice_ticket; if ($stateuri && ($stateuri eq 'tcp') && $migratedfrom && ($rpcenv->{type} eq 'cli')) { @@ -1720,7 +1732,7 @@ __PACKAGE__->register_method({ syslog('info', "start VM $vmid: $upid\n"); PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef, - $machine, $spice_ticket, $migration_network, $migration_type); + $machine, $spice_ticket, $migration_network, $migration_type, $targetstorage); return; }; diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 3b849644..e7071c07 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -4449,7 +4449,7 @@ sub vmconfig_update_disk { sub vm_start { my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, - $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_; + $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_; PVE::QemuConfig->lock_config($vmid, sub { my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom); @@ -4470,6 +4470,55 @@ sub vm_start { # set environment variable useful inside network script $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom; + my $local_volumes = {}; + + if( $targetstorage ){ + + foreach_drive($conf, sub { + my ($ds, $drive) = @_; + + return if drive_is_cdrom($drive); + + my $volid = $drive->{file}; + + return if !$volid; + + my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid); + + my $scfg = PVE::Storage::storage_config($storecfg, $storeid); + return if $scfg->{shared}; + $local_volumes->{$ds} = [$volid, $storeid, $volname]; + }); + + my $format = undef; + + foreach my $opt (sort keys %$local_volumes) { + + my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}}; + my $drive = parse_drive($opt, $conf->{$opt}); + + #if remote storage is specified, use default format + if ($targetstorage && $targetstorage ne "1") { + $storeid = $targetstorage; + my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid); + $format = $defFormat; + } else { + #else we use same format than original + my $scfg = PVE::Storage::storage_config($storecfg, $storeid); + $format = qemu_img_format($scfg, $volid); + } + + my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024)); + my $newdrive = $drive; + $newdrive->{format} = $format; + $newdrive->{file} = $newvolid; + my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive); + $local_volumes->{$opt} = $drivestr; + #pass drive to conf for command line + $conf->{$opt} = $drivestr; + } + } + my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine); my $migrate_port = 0; @@ -4607,6 +4656,27 @@ sub vm_start { warn $@ if $@; } + #start nbd server for storage migration + if ($targetstorage) { + + my $nodename = PVE::INotify::nodename(); + my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network); + my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1); + my $pfamily = PVE::Tools::get_host_address_family($nodename); + $migrate_port = PVE::Tools::next_migrate_port($pfamily); + + vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet', data => { host => "${localip}", port => "${migrate_port}" } } ); + + $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip); + + foreach my $opt (sort keys %$local_volumes) { + my $volid = $local_volumes->{$opt}; + vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true ); + my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt"; + print "storage migration listens on $migrate_storage_uri volume:$volid\n"; + } + } + if ($migratedfrom) { eval {