use PVE::GuestHelpers;
use PVE::QemuConfig;
use PVE::QemuServer;
+use PVE::QemuServer::Drive;
use PVE::QemuServer::Monitor qw(mon_cmd);
use PVE::QemuMigrate;
use PVE::RPCEnvironment;
return $res;
}});
+my $parse_restore_archive = sub {
+ my ($storecfg, $archive) = @_;
+
+ my ($archive_storeid, $archive_volname) = PVE::Storage::parse_volume_id($archive);
+
+ if (defined($archive_storeid)) {
+ my $scfg = PVE::Storage::storage_config($storecfg, $archive_storeid);
+ if ($scfg->{type} eq 'pbs') {
+ return {
+ type => 'pbs',
+ volid => $archive,
+ };
+ }
+ }
+ my $path = PVE::Storage::abs_filesystem_path($storecfg, $archive);
+ return {
+ type => 'file',
+ path => $path,
+ };
+};
__PACKAGE__->register_method({
node => get_standard_option('pve-node'),
vmid => get_standard_option('pve-vmid', { completion => \&PVE::Cluster::complete_next_vmid }),
archive => {
- description => "The backup file.",
+ description => "The backup archive. Either the file system path to a .tar or .vma file (use '-' to pipe data from stdin) or a proxmox storage backup volume identifier.",
type => 'string',
optional => 1,
maxLength => 255,
if ($archive eq '-') {
die "pipe requires cli environment\n"
if $rpcenv->{type} ne 'cli';
+ $archive = { type => 'pipe' };
} else {
PVE::Storage::check_volume_access($rpcenv, $authuser, $storecfg, $vmid, $archive);
- $archive = PVE::Storage::abs_filesystem_path($storecfg, $archive);
+
+ $archive = $parse_restore_archive->($storecfg, $archive);
}
}
die "$emsg vm is running\n" if PVE::QemuServer::check_running($vmid);
my $realcmd = sub {
- PVE::QemuServer::restore_archive($archive, $vmid, $authuser, {
+ my $restore_options = {
storage => $storage,
pool => $pool,
unique => $unique,
bwlimit => $bwlimit,
- });
+ };
+ if ($archive->{type} eq 'file' || $archive->{type} eq 'pipe') {
+ PVE::QemuServer::restore_file_archive($archive->{path} // '-', $vmid, $authuser, $restore_options);
+ } elsif ($archive->{type} eq 'pbs') {
+ PVE::QemuServer::restore_proxmox_backup_archive($archive->{volid}, $vmid, $authuser, $restore_options);
+ } else {
+ die "unknown backup archive type\n";
+ }
my $restored_conf = PVE::QemuConfig->load_config($vmid);
# Convert restored VM to template if backup was VM template
if (PVE::QemuConfig->is_template($restored_conf)) {
$vollist = &$create_disks($rpcenv, $authuser, $conf, $arch, $storecfg, $vmid, $pool, $param, $storage);
if (!$conf->{bootdisk}) {
- my $firstdisk = PVE::QemuServer::resolve_first_disk($conf);
+ my $firstdisk = PVE::QemuServer::Drive::resolve_first_disk($conf);
$conf->{bootdisk} = $firstdisk if $firstdisk;
}
my $conf = PVE::QemuConfig->load_config($vmid);
my $storecfg = PVE::Storage::config();
PVE::QemuConfig->check_protection($conf, "can't remove VM $vmid");
- die "unable to remove VM $vmid - used in HA resources\n"
- if PVE::HA::Config::vm_is_ha_managed($vmid);
+
+ my $ha_managed = PVE::HA::Config::service_is_configured("vm:$vmid");
if (!$param->{purge}) {
+ die "unable to remove VM $vmid - used in HA resources and purge parameter not set.\n"
+ if $ha_managed;
# don't allow destroy if with replication jobs but no purge param
my $repl_conf = PVE::ReplicationConfig->new();
$repl_conf->check_for_existing_jobs($vmid);
PVE::AccessControl::remove_vm_access($vmid);
PVE::Firewall::remove_vmfw_conf($vmid);
if ($param->{purge}) {
+ print "purging VM $vmid from related configurations..\n";
PVE::ReplicationConfig::remove_vmid_jobs($vmid);
PVE::VZDump::Plugin::remove_vmid_from_backup_jobs($vmid);
+
+ if ($ha_managed) {
+ PVE::HA::Config::delete_service_from_config("vm:$vmid");
+ print "NOTE: removed VM $vmid from HA resource configuration.\n";
+ }
}
# only now remove the zombie config, else we can have reuse race
disk => {
type => 'string',
description => "The disk you want to move.",
- enum => [ PVE::QemuServer::valid_drive_names() ],
+ enum => [PVE::QemuServer::Drive::valid_drive_names()],
},
storage => get_standard_option('pve-storage-id', {
description => "Target storage.",
(!$format || !$oldfmt || $oldfmt eq $format);
# this only checks snapshots because $disk is passed!
- my $snapshotted = PVE::QemuServer::is_volume_in_use($storecfg, $conf, $disk, $old_volid);
+ my $snapshotted = PVE::QemuServer::Drive::is_volume_in_use($storecfg, $conf, $disk, $old_volid);
die "you can't move a disk with snapshots and delete the source\n"
if $snapshotted && $param->{delete};
disk => {
type => 'string',
description => "The disk you want to resize.",
- enum => [PVE::QemuServer::valid_drive_names()],
+ enum => [PVE::QemuServer::Drive::valid_drive_names()],
},
size => {
type => 'string',
PVE::QemuServer::qemu_block_resize($vmid, "drive-$disk", $storecfg, $volid, $newsize);
- $drive->{size} = $newsize;
+ my $effective_size = eval { PVE::Storage::volume_size_info($storecfg, $volid, 3); };
+ $drive->{size} = $effective_size // $newsize;
$conf->{$disk} = PVE::QemuServer::print_drive($drive);
PVE::QemuConfig->write_config($vmid, $conf);
optional => 1,
type => 'string',
description => "If you want to convert only 1 disk to base image.",
- enum => [PVE::QemuServer::valid_drive_names()],
+ enum => [PVE::QemuServer::Drive::valid_drive_names()],
},
},