]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer.pm
parse_config: optional strict mode
[qemu-server.git] / PVE / QemuServer.pm
index 8c55dbcf6dcfd003a42f4013075a8f93f7805025..2b7ac40494645dab1b857088fd5f579141bd24dc 100644 (file)
@@ -119,21 +119,6 @@ PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
        optional => 1,
 });
 
-
-sub map_storage {
-    my ($map, $source) = @_;
-
-    return $source if !defined($map);
-
-    return $map->{entries}->{$source}
-       if $map->{entries} && defined($map->{entries}->{$source});
-
-    return $map->{default} if $map->{default};
-
-    # identity (fallback)
-    return $source;
-}
-
 PVE::JSONSchema::register_standard_option('pve-targetstorage', {
     description => "Mapping from source to target storages. Providing only a single storage ID maps all source storages to that storage. Providing the special value '1' will map each source storage to itself.",
     type => 'string',
@@ -929,13 +914,10 @@ my $net_fmt = {
         default_key => 1,
     },
     (map { $_ => { keyAlias => 'model', alias => 'macaddr' }} @$nic_model_list),
-    bridge => {
-       type => 'string',
+    bridge => get_standard_option('pve-bridge-id', {
        description => $net_fmt_bridge_descr,
-       format_description => 'bridge',
-       pattern => '[-_.\w\d]+',
        optional => 1,
-    },
+    }),
     queues => {
        type => 'integer',
        minimum => 0, maximum => 16,
@@ -2330,7 +2312,7 @@ sub destroy_vm {
 }
 
 sub parse_vm_config {
-    my ($filename, $raw) = @_;
+    my ($filename, $raw, $strict) = @_;
 
     return if !defined($raw);
 
@@ -2340,6 +2322,16 @@ sub parse_vm_config {
        pending => {},
     };
 
+    my $handle_error = sub {
+       my ($msg) = @_;
+
+       if ($strict) {
+           die $msg;
+       } else {
+           warn $msg;
+       }
+    };
+
     $filename =~ m|/qemu-server/(\d+)\.conf$|
        || die "got strange filename '$filename'";
 
@@ -2394,14 +2386,14 @@ sub parse_vm_config {
            if ($section eq 'pending') {
                $conf->{delete} = $value; # we parse this later
            } else {
-               warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
+               $handle_error->("vm $vmid - property 'delete' is only allowed in [PENDING]\n");
            }
        } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(.+?)\s*$/) {
            my $key = $1;
            my $value = $2;
            eval { $value = check_type($key, $value); };
            if ($@) {
-               warn "vm $vmid - unable to parse value of '$key' - $@";
+               $handle_error->("vm $vmid - unable to parse value of '$key' - $@");
            } else {
                $key = 'ide2' if $key eq 'cdrom';
                my $fmt = $confdesc->{$key}->{format};
@@ -2411,7 +2403,7 @@ sub parse_vm_config {
                        $v->{file} = $volid;
                        $value = print_drive($v);
                    } else {
-                       warn "vm $vmid - unable to parse value of '$key'\n";
+                       $handle_error->("vm $vmid - unable to parse value of '$key'\n");
                        next;
                    }
                }
@@ -2419,7 +2411,7 @@ sub parse_vm_config {
                $conf->{$key} = $value;
            }
        } else {
-           warn "vm $vmid - unable to parse config: $line\n";
+           $handle_error->("vm $vmid - unable to parse config: $line\n");
        }
     }
 
@@ -4998,6 +4990,8 @@ sub vmconfig_delete_or_detach_drive {
 sub vmconfig_apply_pending {
     my ($vmid, $conf, $storecfg, $errors) = @_;
 
+    return if !scalar(keys %{$conf->{pending}});
+
     my $add_apply_error = sub {
        my ($opt, $msg) = @_;
        my $err_msg = "unable to apply pending change $opt : $msg";
@@ -5238,6 +5232,7 @@ sub vm_migrate_get_nbd_disks {
        my ($ds, $drive) = @_;
 
        return if drive_is_cdrom($drive);
+       return if $ds eq 'tpmstate0';
 
        my $volid = $drive->{file};
 
@@ -5276,7 +5271,7 @@ sub vm_migrate_alloc_nbd_disks {
        # volume is not available there, fall back to the default format.
        # Otherwise use the same format as the original.
        if (!$storagemap->{identity}) {
-           $storeid = map_storage($storagemap, $storeid);
+           $storeid = PVE::JSONSchema::map_id($storagemap, $storeid);
            my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
            my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
            my $fileFormat = qemu_img_format($scfg, $volname);
@@ -5369,7 +5364,8 @@ sub vm_start {
 #   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
+#   replicated_volumes => which volids should be re-used with bitmaps for nbd migration
+#   tpmstate_vol => new volid of tpmstate0, not yet contained in config
 sub vm_start_nolock {
     my ($storecfg, $vmid, $conf, $params, $migrate_opts) = @_;
 
@@ -5394,6 +5390,13 @@ sub vm_start_nolock {
     # this way we can reuse the old ISO with the correct config
     PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid) if !$migratedfrom;
 
+    # override TPM state vol if migrated, conf is out of date still
+    if (my $tpmvol = $migrate_opts->{tpmstate_vol}) {
+        my $parsed = parse_drive("tpmstate0", $conf->{tpmstate0});
+        $parsed->{file} = $tpmvol;
+        $conf->{tpmstate0} = print_drive($parsed);
+    }
+
     my $defaults = load_defaults();
 
     # set environment variable useful inside network script
@@ -5501,7 +5504,12 @@ sub vm_start_nolock {
        $pci_devices->{$i} = parse_hostpci($dev);
     }
 
-    my $pci_id_list = [ map { $_->{id} } map { $_->{pciid}->@* } values $pci_devices->%* ];
+    # do not reserve pciid for mediated devices, sysfs will error out for duplicate assignment
+    my $real_pci_devices = [ grep { !(defined($_->{mdev}) && scalar($_->{pciid}->@*) == 1) } values $pci_devices->%* ];
+
+    # map to a flat list of pci ids
+    my $pci_id_list = [ map { $_->{id} } map { $_->{pciid}->@* } $real_pci_devices->@* ];
+
     # reserve all PCI IDs before actually doing anything with them
     PVE::QemuServer::PCI::reserve_pci_usage($pci_id_list, $vmid, $start_timeout);
 
@@ -7450,9 +7458,11 @@ sub qemu_drive_mirror_monitor {
                    if ($agent_running) {
                        print "freeze filesystem\n";
                        eval { mon_cmd($vmid, "guest-fsfreeze-freeze"); };
+                       warn $@ if $@;
                    } else {
                        print "suspend vm\n";
                        eval { PVE::QemuServer::vm_suspend($vmid, 1); };
+                       warn $@ if $@;
                    }
 
                    # if we clone a disk for a new target vm, we don't switch the disk
@@ -7461,9 +7471,11 @@ sub qemu_drive_mirror_monitor {
                    if ($agent_running) {
                        print "unfreeze filesystem\n";
                        eval { mon_cmd($vmid, "guest-fsfreeze-thaw"); };
+                       warn $@ if $@;
                    } else {
                        print "resume vm\n";
-                       eval {  PVE::QemuServer::vm_resume($vmid, 1, 1); };
+                       eval { PVE::QemuServer::vm_resume($vmid, 1, 1); };
+                       warn $@ if $@;
                    }
 
                    last;
@@ -7622,8 +7634,8 @@ sub clone_disk {
 no_data_clone:
     my ($size) = eval { PVE::Storage::volume_size_info($storecfg, $newvolid, 10) };
 
-    my $disk = $drive;
-    $disk->{format} = undef;
+    my $disk = dclone($drive);
+    delete $disk->{format};
     $disk->{file} = $newvolid;
     $disk->{size} = $size if defined($size);