]>
Commit | Line | Data |
---|---|---|
93285df8 DM |
1 | #!/usr/bin/perl |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use POSIX; | |
6 | use File::Path; | |
7 | ||
8 | use PVE::SafeSyslog; | |
9 | use PVE::Tools; | |
10 | use PVE::Cluster; | |
93285df8 DM |
11 | use PVE::RPCEnvironment; |
12 | use PVE::JSONSchema qw(get_standard_option); | |
13 | use PVE::CLIHandler; | |
14 | use PVE::Storage; | |
15 | use PVE::LXC; | |
7af97ad5 | 16 | use PVE::LXC::Setup; |
93285df8 DM |
17 | use Data::Dumper; |
18 | ||
19 | use base qw(PVE::CLIHandler); | |
20 | ||
21 | $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin'; | |
22 | ||
23 | initlog ('lxc-pve-mount-hook'); | |
24 | ||
25 | die "please run as root\n" if $> != 0; | |
26 | ||
93285df8 DM |
27 | my $rpcenv = PVE::RPCEnvironment->init('cli'); |
28 | $rpcenv->set_language($ENV{LANG}); | |
29 | $rpcenv->set_user('root@pam'); | |
30 | ||
31 | # we cannot use cfs_read here (permission problem) | |
f04c2ae2 DM |
32 | # $rpcenv->init_request(); |
33 | # PVE::INotify::nodename() also returns wrong value! | |
93285df8 DM |
34 | |
35 | __PACKAGE__->register_method ({ | |
36 | name => 'lxc-pve-mount-hook', | |
37 | path => 'lxc-pve-mount-hook', | |
38 | method => 'GET', | |
39 | description => "Create a new container root directory.", | |
40 | parameters => { | |
41 | additionalProperties => 0, | |
42 | properties => { | |
4fc1b360 | 43 | name => { |
c0c77476 | 44 | description => "The container name. This hook is only active for containers using numeric IDs, where configuration is stored on /etc/pve/lxc/<name>.conf (else it is just a NOP).", |
4fc1b360 DM |
45 | type => 'string', |
46 | pattern => '\S+', | |
47 | maxLength => 64, | |
48 | }, | |
93285df8 DM |
49 | path => { |
50 | description => "The path to the container configuration directory (LXC internal argument - do not pass manually!).", | |
51 | type => 'string', | |
52 | }, | |
53 | rootfs => { | |
54 | description => "The path to the container's rootfs (LXC internal argument - do not pass manually!)", | |
55 | type => 'string', | |
56 | }, | |
57 | }, | |
58 | }, | |
59 | returns => { type => 'null' }, | |
60 | ||
61 | code => sub { | |
62 | my ($param) = @_; | |
63 | ||
64 | my $private = $param->{rootfs}; | |
65 | ||
4fc1b360 | 66 | return undef if $param->{name} !~ m/^\d+$/; |
93285df8 | 67 | |
f04c2ae2 DM |
68 | my $vmid = $param->{name}; |
69 | ||
27916659 DM |
70 | # Note: PVE::INotify::nodename() returns wrong value when run |
71 | # inside container mount hook, so we cannot simply | |
72 | # use PVE::LXC::load_conf(). | |
93285df8 | 73 | |
27916659 DM |
74 | my $config_filename = "/etc/pve/lxc/$param->{name}.conf"; |
75 | ||
76 | return undef if ! -f $config_filename; | |
77 | ||
78 | my $raw = PVE::Tools::file_get_contents($config_filename); | |
79 | my $conf = PVE::LXC::parse_pct_config($config_filename, $raw); | |
80 | ||
f04c2ae2 DM |
81 | my $rootdir = $ENV{LXC_ROOTFS_MOUNT}; |
82 | ||
83 | # Note: PVE::Storage::config() does not work here | |
84 | my $fn = "/etc/pve/storage.cfg"; | |
85 | $raw = -f $fn ? PVE::Tools::file_get_contents($fn) : ''; | |
86 | my $storage_cfg = PVE::Storage::Plugin->parse_config($fn, $raw); | |
87 | ||
88 | my $bdevs = PVE::LXC::blockdevices_list(); | |
89 | my $loopdevs = PVE::LXC::loopdevices_list(); | |
90 | ||
91 | my $setup_mountpoint = sub { | |
92 | my ($ms, $mountpoint) = @_; | |
93 | ||
cc6b0307 | 94 | return if $ms eq 'rootfs'; |
1e8f01be | 95 | PVE::LXC::mountpoint_mount($mountpoint, $rootdir, $storage_cfg, $loopdevs); |
892e1d03 | 96 | }; |
f04c2ae2 | 97 | |
892e1d03 AD |
98 | my $setup_cgroup_device = sub { |
99 | my ($ms, $mountpoint) = @_; | |
f04c2ae2 | 100 | |
892e1d03 AD |
101 | my $volid = $mountpoint->{volume}; |
102 | return if !$volid || $volid =~ m|^/dev/.+|; | |
103 | ||
a3076d81 | 104 | my $path = PVE::LXC::volid_path($volid, $storage_cfg, $loopdevs); |
f04c2ae2 DM |
105 | |
106 | if (-l $path) { | |
107 | $path = readlink($path); | |
108 | $path =~ s/\.\.\/\.\.\//\/dev\//; | |
109 | } | |
110 | ||
111 | if ($bdevs->{$path}) { | |
112 | PVE::Tools::run_command(['mknod', '-m', '666', "$rootdir$path", 'b', $bdevs->{$path}->{major}, $bdevs->{$path}->{minor}]); | |
113 | PVE::LXC::write_cgroup_value("devices", $vmid, "devices.allow", "b $bdevs->{$path}->{major}:$bdevs->{$path}->{minor} rwm"); | |
114 | } | |
f04c2ae2 | 115 | }; |
5b4657d0 | 116 | |
f04c2ae2 | 117 | PVE::LXC::foreach_mountpoint($conf, $setup_mountpoint); |
f5635601 | 118 | |
892e1d03 AD |
119 | PVE::LXC::foreach_mountpoint($conf, $setup_cgroup_device); |
120 | ||
7af97ad5 | 121 | my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir); |
d66768a2 | 122 | $lxc_setup->pre_start_hook(); |
27916659 | 123 | |
93285df8 DM |
124 | return undef; |
125 | }}); | |
126 | ||
127 | ||
128 | push @ARGV, 'help' if !scalar(@ARGV); | |
129 | ||
130 | my $param = {}; | |
131 | ||
132 | if ((scalar(@ARGV) == 1) && ($ARGV[0] eq 'printmanpod') || | |
133 | ($ARGV[0] eq 'verifyapi')) { | |
134 | # OK | |
135 | } elsif ((scalar(@ARGV) == 3) && ($ARGV[1] eq 'lxc') && ($ARGV[2] eq 'mount')) { | |
136 | $param->{name} = $ENV{'LXC_NAME'}; | |
137 | die "got wrong name" if $param->{name} ne $ARGV[0]; | |
5b4657d0 | 138 | |
93285df8 DM |
139 | $param->{path} = $ENV{'LXC_CONFIG_FILE'}; |
140 | $param->{rootfs} = $ENV{'LXC_ROOTFS_PATH'}; | |
141 | @ARGV = (); | |
142 | } else { | |
143 | @ARGV = ('help'); | |
144 | } | |
145 | ||
146 | my $cmddef = [ __PACKAGE__, 'lxc-pve-mount-hook', [], $param]; | |
147 | ||
148 | PVE::CLIHandler::handle_simple_cmd($cmddef, \@ARGV, undef, $0); | |
149 | ||
150 | exit 0; | |
151 | ||
152 | __END__ | |
153 | ||
154 | =head1 NAME | |
155 | ||
156 | lxc-pve - LXC mount hook for Proxmox VE | |
157 | ||
158 | =head1 SYNOPSIS | |
159 | ||
160 | =include synopsis | |
161 | ||
162 | =head1 DESCRIPTION | |
163 | ||
4fc1b360 | 164 | This mount hook sets the network and hostname for pve container. |
93285df8 DM |
165 | |
166 | =head1 SEE ALSO | |
167 | ||
168 | lct(1) | |
169 | ||
170 | =include pve_copyright |