]>
git.proxmox.com Git - qemu-server.git/blob - qmextract
3b2544564e117e62fac58bea879f6a08edad07d3
10 use PVE
::Cluster
qw(cfs_read_file);
11 use PVE
::RPCEnvironment
;
14 $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
16 die "please run as root\n" if $> != 0;
18 my @std_opts = ('storage=s', 'pool=s', 'info', 'prealloc');
21 print STDERR
"usage: $0 [--storage=<storeid>] [--pool=<poolid>] [--info] [--prealloc] <archive> <vmid>\n\n";
25 if (!GetOptions
($opts, @std_opts)) {
30 PVE
::INotify
::inotify_init
();
32 my $rpcenv = PVE
::RPCEnvironment-
>init('cli');
34 $rpcenv->init_request();
35 $rpcenv->set_language($ENV{LANG
});
36 $rpcenv->set_user('root@pam');
39 # NOTE: this is run as tar subprocess (--to-command)
41 $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
42 die "interrupted by signal\n";
45 my $filename = $ENV{TAR_FILENAME
};
46 die "got strange environment - no TAR_FILENAME\n" if !$filename;
48 my $filesize = $ENV{TAR_SIZE
};
49 die "got strange file size '$filesize'\n" if !$filesize;
51 my $tmpdir = $ENV{VZDUMP_TMPDIR
};
52 die "got strange environment - no VZDUMP_TMPDIR\n" if !$tmpdir;
54 my $filetype = $ENV{TAR_FILETYPE
} || 'none';
55 die "got strange filetype '$filetype'\n" if $filetype ne 'f';
57 my $vmid = $ENV{VZDUMP_VMID
};
58 PVE
::JSONSchema
::pve_verify_vmid
($vmid);
60 my $user = $ENV{VZDUMP_USER
};
61 $rpcenv->check_user_enabled($user);
64 print STDERR
"reading archive member '$filename'\n";
66 print STDERR
"extracting '$filename' from archive\n";
69 my $conffile = "$tmpdir/qemu-server.conf";
70 my $statfile = "$tmpdir/qmrestore.stat";
72 if ($filename eq 'qemu-server.conf') {
73 my $outfd = IO
::File-
>new($conffile, "w") ||
74 die "unable to write file '$conffile'\n";
76 while (defined(my $line = <>)) {
78 print STDERR
"CONFIG: $line" if $opts->{info
};
87 exec 'dd', 'bs=256K', "of=/dev/null";
88 die "couldn't exec dd: $!\n";
91 my $conffd = IO
::File-
>new($conffile, "r") ||
92 die "unable to read file '$conffile'\n";
95 while (defined(my $line = <$conffd>)) {
96 if ($line =~ m/^\#vzdump\#map:(\S+):(\S+):(\d+):(\S*):$/) {
97 $map->{$2} = { virtdev
=> $1, size
=> $3, storeid
=> $4 };
102 my $statfd = IO
::File-
>new($statfile, "a") ||
103 die "unable to open file '$statfile'\n";
105 if ($filename !~ m/^.*\.([^\.]+)$/){
106 die "got strange filename '$filename'\n";
113 print STDERR
"restoring old style vzdump archive - " .
114 "no device map inside archive\n";
115 die "can't restore old style archive to storage '$opts->{storage}'\n"
116 if defined($opts->{storage
}) && $opts->{storage
} ne 'local';
118 my $dir = "/var/lib/vz/images/$vmid";
121 $path = "$dir/$filename";
123 print $statfd "vzdump::$path\n";
128 my $info = $map->{$filename};
129 die "no vzdump info for '$filename'\n" if !$info;
131 if ($filename !~ m/^vm-disk-$info->{virtdev}\.([^\.]+)$/){
132 die "got strange filename '$filename'\n";
135 if ($filesize != $info->{size
}) {
136 die "detected size difference for '$filename' " .
137 "($filesize != $info->{size})\n";
140 # check permission for all used storages
141 my $pool = $opts->{pool
};
142 if ($user ne 'root@pam') {
143 if (defined($opts->{storage
})) {
144 my $sid = $opts->{storage
} || 'local';
145 $rpcenv->check($user, "/storage/$sid", ['Datastore.AllocateSpace']);
147 foreach my $fn (keys %$map) {
148 my $fi = $map->{$fn};
149 my $sid = $fi->{storeid
} || 'local';
150 $rpcenv->check($user, "/storage/$sid", ['Datastore.AllocateSpace']);
156 if (defined($opts->{storage
})) {
157 $storeid = $opts->{storage
} || 'local';
159 $storeid = $info->{storeid
} || 'local';
162 my $cfg = cfs_read_file
('storage.cfg');
163 my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid);
165 my $alloc_size = ($filesize + 1024 - 1)/1024;
166 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs') {
167 # hack: we just alloc a small file (32K) - we overwrite it anyways
170 die "unable to restore '$filename' to storage '$storeid'\n" .
171 "storage type '$scfg->{type}' does not support format '$format\n"
175 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $storeid, $vmid,
176 $format, undef, $alloc_size);
178 print STDERR
"new volume ID is '$volid'\n";
180 print $statfd "vzdump:$info->{virtdev}:$volid\n";
183 $path = PVE
::Storage
::path
($cfg, $volid);
186 print STDERR
"restore data to '$path' ($filesize bytes)\n";
188 if ($opts->{prealloc
} || $format ne 'raw' || (-b
$path)) {
189 exec 'dd', 'ibs=256K', 'obs=256K', "of=$path";
190 die "couldn't exec dd: $!\n";
192 exec '/usr/lib/qemu-server/sparsecp', $path;
193 die "couldn't exec sparsecp: $!\n";
198 if (scalar(@ARGV) == 2) {
202 # fixme: use API call
203 PVE
::JSONSchema
::pve_verify_vmid
($vmid);
205 PVE
::Cluster
::check_cfs_quorum
();
207 PVE
::QemuServer
::restore_archive
($archive, $vmid, 'root@pam', $opts);
209 } elsif (scalar(@ARGV) == 0 && $ENV{TAR_FILENAME
}) {