]>
Commit | Line | Data |
---|---|---|
b94e047a EK |
1 | package PVE::QemuServer::ImportDisk; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | ||
6 | use PVE::Storage; | |
7 | use PVE::QemuServer; | |
8 | use PVE::Tools qw(run_command extract_param); | |
9 | ||
10 | # imports an external disk image to an existing VM | |
11 | # and creates by default a drive entry unused[n] pointing to the created volume | |
5600c5b2 TL |
12 | # $params->{drive_name} may be used to specify ide0, scsi1, etc ... |
13 | # $params->{format} may be used to specify qcow2, raw, etc ... | |
e6ac9fed DJ |
14 | # $params->{skiplock} may be used to skip checking for a lock in the VM config |
15 | # $params->{'skip-config-update'} may be used to import the disk without updating the VM config | |
b94e047a | 16 | sub do_import { |
5600c5b2 | 17 | my ($src_path, $vmid, $storage_id, $params) = @_; |
b94e047a | 18 | |
5600c5b2 TL |
19 | my $drive_name = extract_param($params, 'drive_name'); |
20 | my $format = extract_param($params, 'format'); | |
b94e047a EK |
21 | if ($drive_name && !(PVE::QemuServer::is_valid_drivename($drive_name))) { |
22 | die "invalid drive name: $drive_name\n"; | |
23 | } | |
24 | ||
25 | # get the needed size from source disk | |
26 | my $src_size = PVE::Storage::file_size_info($src_path); | |
27 | ||
28 | # get target format, target image's path, and whether it's possible to sparseinit | |
29 | my $storecfg = PVE::Storage::config(); | |
5600c5b2 | 30 | my $dst_format = PVE::QemuServer::resolve_dst_disk_format($storecfg, $storage_id, undef, $format); |
b94e047a | 31 | |
5600c5b2 | 32 | my $dst_volid = PVE::Storage::vdisk_alloc($storecfg, $storage_id, $vmid, $dst_format, undef, $src_size / 1024); |
b94e047a | 33 | |
af1f1ec0 | 34 | my $zeroinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $dst_volid); |
b94e047a EK |
35 | |
36 | my $create_drive = sub { | |
37 | my $vm_conf = PVE::QemuConfig->load_config($vmid); | |
5600c5b2 | 38 | if (!$params->{skiplock}) { |
7f384190 DJ |
39 | PVE::QemuConfig->check_lock($vm_conf); |
40 | } | |
b94e047a EK |
41 | |
42 | if ($drive_name) { | |
5600c5b2 TL |
43 | # should never happen as setting $drive_name is not exposed to public interface |
44 | die "cowardly refusing to overwrite existing entry: $drive_name\n" if $vm_conf->{$drive_name}; | |
b94e047a | 45 | |
5600c5b2 TL |
46 | my $modified = {}; # record what $option we modify |
47 | $modified->{$drive_name} = 1; | |
48 | $vm_conf->{pending}->{$drive_name} = $dst_volid; | |
49 | PVE::QemuConfig->write_config($vmid, $vm_conf); | |
b94e047a | 50 | |
5600c5b2 TL |
51 | my $running = PVE::QemuServer::check_running($vmid); |
52 | if ($running) { | |
53 | my $errors = {}; | |
54 | PVE::QemuServer::vmconfig_hotplug_pending($vmid, $vm_conf, $storecfg, $modified, $errors); | |
55 | warn "hotplugging imported disk '$_' failed: $errors->{$_}\n" for keys %$errors; | |
56 | } else { | |
57 | PVE::QemuServer::vmconfig_apply_pending($vmid, $vm_conf, $storecfg); | |
58 | } | |
b94e047a | 59 | } else { |
c75bf161 | 60 | $drive_name = PVE::QemuConfig->add_unused_volume($vm_conf, $dst_volid); |
b94e047a EK |
61 | PVE::QemuConfig->write_config($vmid, $vm_conf); |
62 | } | |
b94e047a EK |
63 | }; |
64 | ||
65 | eval { | |
66 | # trap interrupts so we have a chance to clean up | |
6cb0144a EK |
67 | local $SIG{INT} = |
68 | local $SIG{TERM} = | |
69 | local $SIG{QUIT} = | |
70 | local $SIG{HUP} = | |
5600c5b2 TL |
71 | local $SIG{PIPE} = sub { die "interrupted by signal $!\n"; }; |
72 | ||
b94e047a | 73 | PVE::Storage::activate_volumes($storecfg, [$dst_volid]); |
af1f1ec0 | 74 | PVE::QemuServer::qemu_img_convert($src_path, $dst_volid, $src_size, undef, $zeroinit); |
b94e047a | 75 | PVE::Storage::deactivate_volumes($storecfg, [$dst_volid]); |
e6ac9fed | 76 | PVE::QemuConfig->lock_config($vmid, $create_drive) if !$params->{'skip-config-update'}; |
b94e047a | 77 | }; |
5600c5b2 TL |
78 | if (my $err = $@) { |
79 | eval { PVE::Storage::vdisk_free($storecfg, $dst_volid) }; | |
80 | warn "cleanup of $dst_volid failed: $@\n" if $@; | |
b94e047a EK |
81 | die $err; |
82 | } | |
c75bf161 TL |
83 | |
84 | return ($drive_name, $dst_volid); | |
b94e047a EK |
85 | } |
86 | ||
87 | 1; |