mirror of
https://git.proxmox.com/git/qemu-server
synced 2025-05-04 15:18:49 +00:00
vm_start: split out NBD disk allocation
as preparation of targetstorage mapping and remote migration. this also removes re-using of the $local_volumes hash in the original code. Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
parent
3898a56343
commit
13cfe3b7a7
@ -4709,71 +4709,11 @@ sub vmconfig_update_disk {
|
|||||||
vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive, $arch, $machine_type);
|
vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive, $arch, $machine_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
# see vm_start_nolock for parameters
|
# called in locked context by incoming migration
|
||||||
sub vm_start {
|
sub vm_migrate_alloc_nbd_disks {
|
||||||
my ($storecfg, $vmid, $params, $migrate_opts) = @_;
|
my ($storecfg, $vmid, $conf, $targetstorage, $replicated_volumes) = @_;
|
||||||
|
|
||||||
PVE::QemuConfig->lock_config($vmid, sub {
|
|
||||||
my $conf = PVE::QemuConfig->load_config($vmid, $migrate_opts->{migratedfrom});
|
|
||||||
|
|
||||||
die "you can't start a vm if it's a template\n" if PVE::QemuConfig->is_template($conf);
|
|
||||||
|
|
||||||
$params->{resume} = PVE::QemuConfig->has_lock($conf, 'suspended');
|
|
||||||
|
|
||||||
PVE::QemuConfig->check_lock($conf)
|
|
||||||
if !($params->{skiplock} || $params->{resume});
|
|
||||||
|
|
||||||
die "VM $vmid already running\n" if check_running($vmid, undef, $migrate_opts->{migratedfrom});
|
|
||||||
|
|
||||||
vm_start_nolock($storecfg, $vmid, $conf, $params, $migrate_opts);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# params:
|
|
||||||
# statefile => 'tcp', 'unix' for migration or path/volid for RAM state
|
|
||||||
# skiplock => 0/1, skip checking for config lock
|
|
||||||
# forcemachine => to force Qemu machine (rollback/migration)
|
|
||||||
# timeout => in seconds
|
|
||||||
# paused => start VM in paused state (backup)
|
|
||||||
# resume => resume from hibernation
|
|
||||||
# migrate_opts:
|
|
||||||
# migratedfrom => source node
|
|
||||||
# spice_ticket => used for spice migration, passed via tunnel/stdin
|
|
||||||
# network => CIDR of migration network
|
|
||||||
# type => secure/insecure - tunnel over encrypted connection or plain-text
|
|
||||||
# targetstorage = storageid/'1' - target storage for disks migrated over NBD
|
|
||||||
# nbd_proto_version => int, 0 for TCP, 1 for UNIX
|
|
||||||
# replicated_volumes = which volids should be re-used with bitmaps for nbd migration
|
|
||||||
sub vm_start_nolock {
|
|
||||||
my ($storecfg, $vmid, $conf, $params, $migrate_opts) = @_;
|
|
||||||
|
|
||||||
my $statefile = $params->{statefile};
|
|
||||||
my $resume = $params->{resume};
|
|
||||||
|
|
||||||
my $migratedfrom = $migrate_opts->{migratedfrom};
|
|
||||||
my $migration_type = $migrate_opts->{type};
|
|
||||||
my $targetstorage = $migrate_opts->{targetstorage};
|
|
||||||
|
|
||||||
# clean up leftover reboot request files
|
|
||||||
eval { clear_reboot_request($vmid); };
|
|
||||||
warn $@ if $@;
|
|
||||||
|
|
||||||
if (!$statefile && scalar(keys %{$conf->{pending}})) {
|
|
||||||
vmconfig_apply_pending($vmid, $conf, $storecfg);
|
|
||||||
$conf = PVE::QemuConfig->load_config($vmid); # update/reload
|
|
||||||
}
|
|
||||||
|
|
||||||
PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid);
|
|
||||||
|
|
||||||
my $defaults = load_defaults();
|
|
||||||
|
|
||||||
# set environment variable useful inside network script
|
|
||||||
$ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
|
|
||||||
|
|
||||||
my $local_volumes = {};
|
my $local_volumes = {};
|
||||||
|
|
||||||
if ($targetstorage) {
|
|
||||||
foreach_drive($conf, sub {
|
foreach_drive($conf, sub {
|
||||||
my ($ds, $drive) = @_;
|
my ($ds, $drive) = @_;
|
||||||
|
|
||||||
@ -4792,12 +4732,12 @@ sub vm_start_nolock {
|
|||||||
|
|
||||||
my $format = undef;
|
my $format = undef;
|
||||||
|
|
||||||
|
my $nbd = {};
|
||||||
foreach my $opt (sort keys %$local_volumes) {
|
foreach my $opt (sort keys %$local_volumes) {
|
||||||
|
|
||||||
my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
|
my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
|
||||||
if ($migrate_opts->{replicated_volumes}->{$volid}) {
|
if ($replicated_volumes->{$volid}) {
|
||||||
# re-use existing, replicated volume with bitmap on source side
|
# re-use existing, replicated volume with bitmap on source side
|
||||||
$local_volumes->{$opt} = $conf->{${opt}};
|
$nbd->{$opt} = $conf->{${opt}};
|
||||||
print "re-using replicated volume: $opt - $volid\n";
|
print "re-using replicated volume: $opt - $volid\n";
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
@ -4822,12 +4762,80 @@ sub vm_start_nolock {
|
|||||||
$newdrive->{format} = $format;
|
$newdrive->{format} = $format;
|
||||||
$newdrive->{file} = $newvolid;
|
$newdrive->{file} = $newvolid;
|
||||||
my $drivestr = print_drive($newdrive);
|
my $drivestr = print_drive($newdrive);
|
||||||
$local_volumes->{$opt} = $drivestr;
|
$nbd->{$opt} = $drivestr;
|
||||||
#pass drive to conf for command line
|
#pass drive to conf for command line
|
||||||
$conf->{$opt} = $drivestr;
|
$conf->{$opt} = $drivestr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $nbd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# see vm_start_nolock for parameters, additionally:
|
||||||
|
# migrate_opts:
|
||||||
|
# targetstorage = storageid/'1' - target storage for disks migrated over NBD
|
||||||
|
sub vm_start {
|
||||||
|
my ($storecfg, $vmid, $params, $migrate_opts) = @_;
|
||||||
|
|
||||||
|
PVE::QemuConfig->lock_config($vmid, sub {
|
||||||
|
my $conf = PVE::QemuConfig->load_config($vmid, $migrate_opts->{migratedfrom});
|
||||||
|
|
||||||
|
die "you can't start a vm if it's a template\n" if PVE::QemuConfig->is_template($conf);
|
||||||
|
|
||||||
|
$params->{resume} = PVE::QemuConfig->has_lock($conf, 'suspended');
|
||||||
|
|
||||||
|
PVE::QemuConfig->check_lock($conf)
|
||||||
|
if !($params->{skiplock} || $params->{resume});
|
||||||
|
|
||||||
|
die "VM $vmid already running\n" if check_running($vmid, undef, $migrate_opts->{migratedfrom});
|
||||||
|
|
||||||
|
$migrate_opts->{nbd} = vm_migrate_alloc_nbd_disks($storecfg, $vmid, $conf, $migrate_opts->{targetstorage}, $migrate_opts->{replicated_volumes})
|
||||||
|
if $migrate_opts->{targetstorage};
|
||||||
|
|
||||||
|
vm_start_nolock($storecfg, $vmid, $conf, $params, $migrate_opts);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# statefile => 'tcp', 'unix' for migration or path/volid for RAM state
|
||||||
|
# skiplock => 0/1, skip checking for config lock
|
||||||
|
# forcemachine => to force Qemu machine (rollback/migration)
|
||||||
|
# timeout => in seconds
|
||||||
|
# paused => start VM in paused state (backup)
|
||||||
|
# resume => resume from hibernation
|
||||||
|
# migrate_opts:
|
||||||
|
# nbd => newly allocated volumes for NBD exports (vm_migrate_alloc_nbd_disks)
|
||||||
|
# migratedfrom => source node
|
||||||
|
# spice_ticket => used for spice migration, passed via tunnel/stdin
|
||||||
|
# network => CIDR of migration network
|
||||||
|
# type => secure/insecure - tunnel over encrypted connection or plain-text
|
||||||
|
# nbd_proto_version => int, 0 for TCP, 1 for UNIX
|
||||||
|
# replicated_volumes = which volids should be re-used with bitmaps for nbd migration
|
||||||
|
sub vm_start_nolock {
|
||||||
|
my ($storecfg, $vmid, $conf, $params, $migrate_opts) = @_;
|
||||||
|
|
||||||
|
my $statefile = $params->{statefile};
|
||||||
|
my $resume = $params->{resume};
|
||||||
|
|
||||||
|
my $migratedfrom = $migrate_opts->{migratedfrom};
|
||||||
|
my $migration_type = $migrate_opts->{type};
|
||||||
|
|
||||||
|
# clean up leftover reboot request files
|
||||||
|
eval { clear_reboot_request($vmid); };
|
||||||
|
warn $@ if $@;
|
||||||
|
|
||||||
|
if (!$statefile && scalar(keys %{$conf->{pending}})) {
|
||||||
|
vmconfig_apply_pending($vmid, $conf, $storecfg);
|
||||||
|
$conf = PVE::QemuConfig->load_config($vmid); # update/reload
|
||||||
|
}
|
||||||
|
|
||||||
|
PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid);
|
||||||
|
|
||||||
|
my $defaults = load_defaults();
|
||||||
|
|
||||||
|
# set environment variable useful inside network script
|
||||||
|
$ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
|
||||||
|
|
||||||
PVE::GuestHelpers::exec_hookscript($conf, $vmid, 'pre-start', 1);
|
PVE::GuestHelpers::exec_hookscript($conf, $vmid, 'pre-start', 1);
|
||||||
|
|
||||||
my $forcemachine = $params->{forcemachine};
|
my $forcemachine = $params->{forcemachine};
|
||||||
@ -5027,7 +5035,7 @@ sub vm_start_nolock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#start nbd server for storage migration
|
#start nbd server for storage migration
|
||||||
if ($targetstorage) {
|
if (my $nbd = $migrate_opts->{nbd}) {
|
||||||
my $nbd_protocol_version = $migrate_opts->{nbd_proto_version} // 0;
|
my $nbd_protocol_version = $migrate_opts->{nbd_proto_version} // 0;
|
||||||
|
|
||||||
my $migrate_storage_uri;
|
my $migrate_storage_uri;
|
||||||
@ -5047,8 +5055,8 @@ sub vm_start_nolock {
|
|||||||
$migrate_storage_uri = "nbd:${localip}:${storage_migrate_port}";
|
$migrate_storage_uri = "nbd:${localip}:${storage_migrate_port}";
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach my $opt (sort keys %$local_volumes) {
|
foreach my $opt (sort keys %$nbd) {
|
||||||
my $drivestr = $local_volumes->{$opt};
|
my $drivestr = $nbd->{$opt};
|
||||||
mon_cmd($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
|
mon_cmd($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
|
||||||
print "storage migration listens on $migrate_storage_uri:exportname=drive-$opt volume:$drivestr\n";
|
print "storage migration listens on $migrate_storage_uri:exportname=drive-$opt volume:$drivestr\n";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user