type => 'array',
items => {
type => "object",
- properties => {},
+ properties => $PVE::QemuServer::vmstatus_return_properties,
},
links => [ { rel => 'child', href => "{vmid}" } ],
},
next if !$rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' ], 1);
my $data = $vmstatus->{$vmid};
- $data->{vmid} = int($vmid);
push @$res, $data;
}
PVE::AccessControl::add_vm_to_pool($vmid, $pool) if $pool;
- PVE::API2::Qemu->vm_start({ vmid => $vmid, node => $node }) if $start_after_create;
+ if ($start_after_create) {
+ eval { PVE::API2::Qemu->vm_start({ vmid => $vmid, node => $node }) };
+ warn $@ if $@;
+ }
};
# ensure no old replication state are exists
my $conf = $param;
+ my ($arch, undef) = PVE::QemuServer::get_basic_machine_info($conf);
+
eval {
$vollist = &$create_disks($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $param, $storage);
$conf->{smbios1} = PVE::QemuServer::generate_smbios1_uuid();
}
+ if ((!defined($conf->{vmgenid}) || $conf->{vmgenid} eq '1') && $arch ne 'aarch64') {
+ $conf->{vmgenid} = PVE::QemuServer::generate_uuid();
+ }
+
PVE::QemuConfig->write_config($vmid, $conf);
};
if ($start_after_create) {
print "Execute autostart\n";
- PVE::API2::Qemu->vm_start({vmid => $vmid, node => $node});
+ eval { PVE::API2::Qemu->vm_start({vmid => $vmid, node => $node}) };
+ warn $@ if $@;
}
};
- my $worker_name = $is_restore ? 'qmrestore' : 'qmcreate';
- my $code = $is_restore ? $restorefn : $createfn;
+ my ($code, $worker_name);
+ if ($is_restore) {
+ $worker_name = 'qmrestore';
+ $code = sub {
+ eval { $restorefn->() };
+ if (my $err = $@) {
+ eval { PVE::QemuConfig->remove_lock($vmid, 'create') };
+ warn $@ if $@;
+ die $err;
+ }
+ };
+ } else {
+ $worker_name = 'qmcreate';
+ $code = sub {
+ eval { $createfn->() };
+ if (my $err = $@) {
+ eval {
+ my $conffile = PVE::QemuConfig->config_file($vmid);
+ unlink($conffile)
+ or die "failed to remove config file: $@\n";
+ };
+ warn $@ if $@;
+ die $err;
+ }
+ };
+ }
return $rpcenv->fork_worker($worker_name, $vmid, $authuser, $code);
}});
},
},
returns => {
+ description => "The current VM configuration.",
type => "object",
- properties => {
+ properties => PVE::QemuServer::json_config_properties({
digest => {
type => 'string',
description => 'SHA1 digest of configuration file. This can be used to prevent concurrent modifications.',
}
- },
+ }),
},
code => sub {
my ($param) = @_;
# add macaddr
my $net = PVE::QemuServer::parse_net($param->{$opt});
$param->{$opt} = PVE::QemuServer::print_net($net);
+ } elsif ($opt eq 'vmgenid') {
+ if ($param->{$opt} eq '1') {
+ $param->{$opt} = PVE::QemuServer::generate_uuid();
+ }
}
}
vmid => get_standard_option('pve-vmid'),
},
},
- returns => { type => 'object' },
+ returns => {
+ type => 'object',
+ properties => {
+ %$PVE::QemuServer::vmstatus_return_properties,
+ ha => {
+ description => "HA manager service status.",
+ type => 'object',
+ },
+ spice => {
+ description => "Qemu VGA configuration supports spice.",
+ type => 'boolean',
+ optional => 1,
+ },
+ agent => {
+ description => "Qemu GuestAgent enabled in config.",
+ type => 'boolean',
+ optional => 1,
+ },
+ },
+ },
code => sub {
my ($param) = @_;
$status->{ha} = PVE::HA::Config::get_service_status("vm:$param->{vmid}");
$status->{spice} = 1 if PVE::QemuServer::vga_conf_has_spice($conf->{vga});
-
- $status->{agent} = 1 if $conf->{agent};
+ $status->{agent} = 1 if (PVE::QemuServer::parse_guest_agent($conf)->{enabled});
return $status;
}});
}
# auto generate a new uuid
- my ($uuid, $uuid_str);
- UUID::generate($uuid);
- UUID::unparse($uuid, $uuid_str);
my $smbios1 = PVE::QemuServer::parse_smbios1($newconf->{smbios1} || '');
- $smbios1->{uuid} = $uuid_str;
+ $smbios1->{uuid} = PVE::QemuServer::generate_uuid();
$newconf->{smbios1} = PVE::QemuServer::print_smbios1($smbios1);
+ # auto generate a new vmgenid if the option was set
+ if ($newconf->{vmgenid}) {
+ $newconf->{vmgenid} = PVE::QemuServer::generate_uuid();
+ }
+
delete $newconf->{template};
if ($param->{name}) {
delete $newconf->{lock};
# do not write pending changes
- if ($newconf->{pending}) {
- warn "found pending changes, discarding for clone\n";
+ if (my @changes = keys %{$newconf->{pending}}) {
+ my $pending = join(',', @changes);
+ warn "found pending changes for '$pending', discarding for clone\n";
delete $newconf->{pending};
}
PVE::QemuConfig->write_config($vmid, $conf);
+ if ($running && PVE::QemuServer::parse_guest_agent($conf)->{fstrim_cloned_disks} && PVE::QemuServer::qga_check_running($vmid)) {
+ eval { PVE::QemuServer::vm_mon_cmd($vmid, "guest-fstrim"); };
+ }
+
eval {
# try to deactivate volumes - avoid lvm LVs to be active on several nodes
PVE::Storage::deactivate_volumes($storecfg, [ $newdrive->{file} ])
type => 'array',
items => {
type => "object",
- properties => {},
+ properties => {
+ name => {
+ description => "Snapshot identifier. Value 'current' identifies the current VM.",
+ type => 'string',
+ },
+ vmstate => {
+ description => "Snapshot includes RAM.",
+ type => 'boolean',
+ optional => 1,
+ },
+ description => {
+ description => "Snapshot description.",
+ type => 'string',
+ },
+ snaptime => {
+ description => "Snapshot creation time",
+ type => 'integer',
+ renderer => 'timestamp',
+ optional => 1,
+ },
+ parent => {
+ description => "Parent snapshot identifier.",
+ type => 'string',
+ optional => 1,
+ },
+ },
},
links => [ { rel => 'child', href => "{name}" } ],
},
}
my $running = PVE::QemuServer::check_running($vmid, 1) ? 1 : 0;
- my $current = { name => 'current', digest => $conf->{digest}, running => $running };
+ my $current = {
+ name => 'current',
+ digest => $conf->{digest},
+ running => $running,
+ description => "You are here!",
+ };
$current->{parent} = $conf->{parent} if $conf->{parent};
push @$res, $current;