]> git.proxmox.com Git - pve-container.git/blobdiff - src/PVE/LXC.pm
print_ct_warn_log: use log_warn function from RESTEnvironment
[pve-container.git] / src / PVE / LXC.pm
index dbdec2389b3d1ffd86e634e2c7b9eadef2d74139..ce6d5a532aad98cd537c8b2d3cce830f9651b34d 100644 (file)
@@ -29,11 +29,11 @@ use PVE::Tools qw(
     $IPV4RE
     $IPV6RE
 );
-use PVE::RPCEnvironment;
 use PVE::CpuSet;
 use PVE::Network;
 use PVE::AccessControl;
 use PVE::ProcFSTools;
+use PVE::RESTEnvironment;
 use PVE::Syscall qw(:fsmount);
 use PVE::LXC::Config;
 use PVE::GuestHelpers qw(safe_string_ne safe_num_ne safe_boolean_ne);
@@ -699,7 +699,7 @@ sub update_lxc_config {
            $raw .= "lxc.cgroup.cpu.cfs_quota_us = $value\n";
        }
 
-       my $shares = $conf->{cpuunits} || 1024;
+       my $shares = PVE::CGroup::clamp_cpu_shares($conf->{cpuunits});
        $raw .= "lxc.cgroup.cpu.shares = $shares\n";
     } elsif ($cgv2->{cpu}) {
        # See PVE::CGroup
@@ -709,8 +709,7 @@ sub update_lxc_config {
        }
 
        if (defined(my $shares = $conf->{cpuunits})) {
-           die "cpu weight (shares) must be in range [1, 10000]\n"
-               if $shares < 1 || $shares > 10000;
+           $shares = PVE::CGroup::clamp_cpu_shares($shares);
            $raw .= "lxc.cgroup2.cpu.weight = $shares\n";
        }
     }
@@ -730,7 +729,15 @@ sub update_lxc_config {
        $raw .= "lxc.net.$ind.veth.pair = veth${vmid}i${ind}\n";
        $raw .= "lxc.net.$ind.hwaddr = $d->{hwaddr}\n" if defined($d->{hwaddr});
        $raw .= "lxc.net.$ind.name = $d->{name}\n" if defined($d->{name});
-       $raw .= "lxc.net.$ind.mtu = $d->{mtu}\n" if defined($d->{mtu});
+
+       # Keep container from starting with invalid mtu configuration
+       if (my $mtu = $d->{mtu}) {
+           my $bridge_mtu = PVE::Network::read_bridge_mtu($d->{bridge});
+           die "$k: MTU size '$mtu' is bigger than bridge MTU '$bridge_mtu'\n"
+               if ($mtu > $bridge_mtu);
+
+           $raw .= "lxc.net.$ind.mtu = $mtu\n";
+       }
 
        # Starting with lxc 4.0, we do not patch lxc to execute our up-scripts.
        if ($lxc_major >= 4) {
@@ -864,10 +871,20 @@ sub delete_mountpoint_volume {
 sub destroy_lxc_container {
     my ($storage_cfg, $vmid, $conf, $replacement_conf, $purge_unreferenced) = @_;
 
-    PVE::LXC::Config->foreach_volume_full($conf, {include_unused => 1}, sub {
+    my $volids = {};
+    my $remove_volume = sub {
        my ($ms, $mountpoint) = @_;
-       delete_mountpoint_volume($storage_cfg, $vmid, $mountpoint->{volume});
-    });
+
+       my $volume = $mountpoint->{volume};
+
+       return if $volids->{$volume};
+       $volids->{$volume} = 1;
+
+       delete_mountpoint_volume($storage_cfg, $vmid, $volume);
+    };
+    PVE::LXC::Config->foreach_volume_full($conf, {include_unused => 1}, $remove_volume);
+
+    PVE::LXC::Config->foreach_volume_full($conf->{pending}, {include_unused => 1}, $remove_volume);
 
     if ($purge_unreferenced) { # also remove unreferenced disk
        my $vmdisks = PVE::Storage::vdisk_list($storage_cfg, undef, $vmid, undef, 'rootdir');
@@ -926,7 +943,8 @@ sub update_net {
        } else {
            if (safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
                safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
-               safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
+               safe_num_ne($oldnet->{firewall}, $newnet->{firewall})
+           ) {
 
                if ($oldnet->{bridge}) {
                    PVE::Network::tap_unplug($veth);
@@ -937,10 +955,14 @@ sub update_net {
                    PVE::LXC::Config->write_config($vmid, $conf);
                }
 
+               my ($bridge, $mac, $firewall, $rate) = $newnet->@{'bridge', 'hwaddr', 'firewall', 'rate'};
                if ($have_sdn) {
-                   PVE::Network::SDN::Zones::tap_plug($veth, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
+                   PVE::Network::SDN::Zones::tap_plug(
+                       $veth, $bridge, $newnet->{tag}, $firewall, $newnet->{trunks}, $rate);
+                   PVE::Network::SDN::Zones::add_bridge_fdb($veth, $mac, $bridge, $firewall);
                } else {
-                   PVE::Network::tap_plug($veth, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
+                   PVE::Network::tap_plug(
+                       $veth, $bridge, $newnet->{tag}, $firewall, $newnet->{trunks}, $rate, { mac => $mac });
                }
 
                # This includes the rate:
@@ -973,9 +995,11 @@ sub hotplug_net {
     if ($have_sdn) {
        PVE::Network::SDN::Zones::veth_create($veth, $vethpeer, $newnet->{bridge}, $newnet->{hwaddr});
        PVE::Network::SDN::Zones::tap_plug($veth, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
+       PVE::Network::SDN::Zones::add_bridge_fdb($veth, $newnet->{hwaddr}, $newnet->{bridge}, $newnet->{firewall});
     } else {
        PVE::Network::veth_create($veth, $vethpeer, $newnet->{bridge}, $newnet->{hwaddr});
        PVE::Network::tap_plug($veth, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
+       PVE::Network::add_bridge_fdb($veth, $newnet->{hwaddr}, $newnet->{firewall}); # early returns if brport has learning on
     }
 
     # attach peer in container
@@ -1262,7 +1286,14 @@ sub check_ct_modify_config_perm {
                my $sid = $1;
                $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
            } else {
-               PVE::Storage::check_volume_access($rpcenv, $authuser, $storage_cfg, $vmid, $volid);
+               PVE::Storage::check_volume_access(
+                   $rpcenv,
+                   $authuser,
+                   $storage_cfg,
+                   $vmid,
+                   $volid,
+                   'rootdir',
+               );
            }
        } elsif ($opt eq 'memory' || $opt eq 'swap') {
            $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Memory']);
@@ -1316,6 +1347,10 @@ sub check_ct_modify_config_perm {
        } elsif ($opt eq 'hookscript') {
            # For now this is restricted to root@pam
            raise_perm_exc("changing the hookscript is only allowed for root\@pam");
+       } elsif ($opt eq 'tags') {
+           my $old = $oldconf->{$opt};
+           my $new = $delete ? '' : $newconf->{$opt};
+           PVE::GuestHelpers::assert_tag_permissions($vmid, $old, $new, $rpcenv, $authuser);
        } else {
            $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Options']);
        }
@@ -1797,7 +1832,7 @@ sub __mountpoint_mount {
     die "unsupported storage";
 }
 
-sub mountpoint_hotplug($$$) {
+sub mountpoint_hotplug :prototype($$$$$) {
     my ($vmid, $conf, $opt, $mp, $storage_cfg) = @_;
 
     my (undef, $rootuid, $rootgid) = PVE::LXC::parse_id_maps($conf);
@@ -2296,13 +2331,8 @@ my sub print_ct_warn_log {
     my $log = eval { file_get_contents($log_fn) };
     return if !$log;
 
-    my $rpcenv = eval { PVE::RPCEnvironment::get() };
-
-    my $warn_fn = $rpcenv ? sub { $rpcenv->warn($_[0]) } : sub { print STDERR "WARN: $_[0]\n" };
-
     while ($log =~ /^\h*\s*(.*?)\h*$/gm) {
-       my $line = $1;
-       $warn_fn->($line);
+       PVE::RESTEnvironment::log_warn($1);
     }
     unlink $log_fn or warn "could not unlink '$log_fn' - $!\n";
 }