]>
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 | ||
94 | my $volid = $mountpoint->{volume}; | |
95 | return if !$volid; | |
96 | ||
27163d2f AD |
97 | if ($volid =~ m|^/dev/.+| && $mountpoint->{mp} && $ms ne 'rootfs') { |
98 | PVE::Tools::run_command(['mount', $volid, "$rootdir$mountpoint->{mp}"]); | |
99 | return; | |
100 | } | |
101 | ||
f04c2ae2 DM |
102 | my ($storage, $volname) = PVE::Storage::parse_volume_id($volid); |
103 | ||
104 | my $scfg = PVE::Storage::storage_config($storage_cfg, $storage); | |
105 | ||
106 | my $path = PVE::Storage::path($storage_cfg, $volid); | |
107 | ||
108 | my ($vtype, undef, undef, undef, undef, $isBase, $format) = | |
109 | PVE::Storage::parse_volname($storage_cfg, $volid); | |
110 | ||
111 | return if $format eq 'subvol'; | |
112 | ||
113 | if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs') { | |
114 | $path = PVE::LXC::find_loopdev($loopdevs, $path); | |
115 | } | |
116 | ||
117 | if (-l $path) { | |
118 | $path = readlink($path); | |
119 | $path =~ s/\.\.\/\.\.\//\/dev\//; | |
120 | } | |
121 | ||
122 | if ($bdevs->{$path}) { | |
123 | PVE::Tools::run_command(['mknod', '-m', '666', "$rootdir$path", 'b', $bdevs->{$path}->{major}, $bdevs->{$path}->{minor}]); | |
124 | PVE::LXC::write_cgroup_value("devices", $vmid, "devices.allow", "b $bdevs->{$path}->{major}:$bdevs->{$path}->{minor} rwm"); | |
125 | } | |
126 | ||
127 | if ($mountpoint->{mp} && ($ms ne 'rootfs')) { | |
128 | PVE::Tools::run_command(['mount', $path, "$rootdir$mountpoint->{mp}"]); | |
129 | } | |
130 | }; | |
5b4657d0 | 131 | |
f04c2ae2 | 132 | PVE::LXC::foreach_mountpoint($conf, $setup_mountpoint); |
f5635601 | 133 | |
7af97ad5 | 134 | my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir); |
d66768a2 | 135 | $lxc_setup->pre_start_hook(); |
27916659 | 136 | |
93285df8 DM |
137 | return undef; |
138 | }}); | |
139 | ||
140 | ||
141 | push @ARGV, 'help' if !scalar(@ARGV); | |
142 | ||
143 | my $param = {}; | |
144 | ||
145 | if ((scalar(@ARGV) == 1) && ($ARGV[0] eq 'printmanpod') || | |
146 | ($ARGV[0] eq 'verifyapi')) { | |
147 | # OK | |
148 | } elsif ((scalar(@ARGV) == 3) && ($ARGV[1] eq 'lxc') && ($ARGV[2] eq 'mount')) { | |
149 | $param->{name} = $ENV{'LXC_NAME'}; | |
150 | die "got wrong name" if $param->{name} ne $ARGV[0]; | |
5b4657d0 | 151 | |
93285df8 DM |
152 | $param->{path} = $ENV{'LXC_CONFIG_FILE'}; |
153 | $param->{rootfs} = $ENV{'LXC_ROOTFS_PATH'}; | |
154 | @ARGV = (); | |
155 | } else { | |
156 | @ARGV = ('help'); | |
157 | } | |
158 | ||
159 | my $cmddef = [ __PACKAGE__, 'lxc-pve-mount-hook', [], $param]; | |
160 | ||
161 | PVE::CLIHandler::handle_simple_cmd($cmddef, \@ARGV, undef, $0); | |
162 | ||
163 | exit 0; | |
164 | ||
165 | __END__ | |
166 | ||
167 | =head1 NAME | |
168 | ||
169 | lxc-pve - LXC mount hook for Proxmox VE | |
170 | ||
171 | =head1 SYNOPSIS | |
172 | ||
173 | =include synopsis | |
174 | ||
175 | =head1 DESCRIPTION | |
176 | ||
4fc1b360 | 177 | This mount hook sets the network and hostname for pve container. |
93285df8 DM |
178 | |
179 | =head1 SEE ALSO | |
180 | ||
181 | lct(1) | |
182 | ||
183 | =include pve_copyright |