]> git.proxmox.com Git - pve-container.git/blame - src/PVE/LXCCreate.pm
implement disk size parameter
[pve-container.git] / src / PVE / LXCCreate.pm
CommitLineData
5b4657d0
DM
1package PVE::LXCCreate;
2
3use strict;
4use warnings;
5use File::Basename;
6use File::Path;
7use Data::Dumper;
8
9use PVE::Storage;
10use PVE::LXC;
11use PVE::LXCSetup;
12
13sub restore_archive {
14 my ($archive, $rootdir, $conf) = @_;
15
16 # we always use the same mapping: 'b:0:100000:65536'
17 my $userns_cmd;
18
19 if ($conf->{'lxc.id_map'}) {
20 $userns_cmd = ['lxc-usernsexec', '-m', 'b:0:100000:65536', '--'];
21 } else {
22 $userns_cmd = [];
23 }
24
25 my $cmd;
26
27 if ($conf->{'lxc.id_map'}) {
28 PVE::Tools::run_command(['chown', '-R', '100000:100000', $rootdir]);
29 }
30
31 $cmd = [@$userns_cmd, 'tar', 'xpf', $archive, '--numeric-owner', '--totals',
32 '--sparse', '-C', $rootdir];
33
34 push @$cmd, '--anchored';
35 push @$cmd, '--exclude' , './dev/*';
36
37 print "extracting archive '$archive'\n";
38 PVE::Tools::run_command($cmd);
39
40 # is this really required? what for?
41 #$cmd = [@$userns_cmd, 'mkdir', '-p', "$rootdir/dev/pts"];
42 #PVE::Tools::run_command($cmd);
43
44 # template/OS specific configuration
45 $conf->{'lxc.arch'} = 'i386'; #fixme: || x86_64
46}
47
48sub restore_and_configure {
49 my ($vmid, $archive, $rootdir, $conf, $password) = @_;
50
51 restore_archive($archive, $rootdir, $conf);
52
53 PVE::LXC::write_config($vmid, $conf);
54
55 my $lxc_setup = PVE::LXCSetup->new($conf, $rootdir); # detect OS
56
57 PVE::LXC::write_config($vmid, $conf); # safe config (after OS detection)
58
59 $lxc_setup->post_create_hook($password);
60}
61
62# directly use a storage directory
63sub create_rootfs_dir {
10fc3ba5 64 my ($cleanup, $storage_conf, $storage, $vmid, $conf, $archive, $password) = @_;
5b4657d0 65
10fc3ba5 66 # note: there is no size limit
5b4657d0
DM
67
68 my $private = PVE::Storage::get_private_dir($storage_conf, $storage, $vmid);
69 mkdir($private) || die "unable to create container private dir '$private' - $!\n";
70
71 push @{$cleanup->{files}}, $private;
72 $conf->{'lxc.rootfs'} = $private;
73
74 restore_and_configure($vmid, $archive, $private, $conf, $password);
75}
76
77# create a raw file, then loop mount
78sub create_rootfs_dir_loop {
79 my ($cleanup, $storage_conf, $storage, $size, $vmid, $conf, $archive, $password) = @_;
80
81 my $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'raw', "vm-$vmid-rootfs.raw", $size);
82
83 push @{$cleanup->{volids}}, $volid;
84
85 my $image_path = PVE::Storage::path($storage_conf, $volid);
86 $conf->{'lxc.rootfs'} = "loop:${image_path}";
87
88 my $cmd = ['mkfs.ext4', $image_path];
89 PVE::Tools::run_command($cmd);
90
91 print "allocated image: $image_path\n";
92
93 my $mountpoint;
94
95 my $loopdev;
96 eval {
97 my $parser = sub {
98 my $line = shift;
99 $loopdev = $line if $line =~m|^/dev/loop\d+$|;
100 };
101 PVE::Tools::run_command(['losetup', '--find', '--show', $image_path], outfunc => $parser);
102
103 my $tmp = "/var/lib/lxc/$vmid/rootfs";
104 File::Path::mkpath($tmp);
105 PVE::Tools::run_command(['mount', '-t', 'ext4', $loopdev, $tmp]);
106 $mountpoint = $tmp;
107
108 restore_and_configure($vmid, $archive, $mountpoint, $conf, $password);
109 };
110 if (my $err = $@) {
111 if ($mountpoint) {
112 eval { PVE::Tools::run_command(['umount', '-d', $mountpoint]) };
113 warn $@ if $@;
114 } else {
115 eval { PVE::Tools::run_command(['losetup', '-d', $loopdev]) if $loopdev; };
116 warn $@ if $@;
117 }
118 die $err;
119 }
120
121 PVE::Tools::run_command(['umount', '-l', '-d', $mountpoint]);
122}
123
124sub create_rootfs {
125 my ($storage_conf, $storage, $size, $vmid, $conf, $archive, $password) = @_;
126
127 PVE::LXC::create_config($vmid, $conf);
128
129 my $cleanup = { files => [], volids => [] };
130
131 eval {
132 my $scfg = PVE::Storage::storage_config($storage_conf, $storage);
133 if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs') {
10fc3ba5 134 if ($size > 0) {
5b4657d0
DM
135 create_rootfs_dir_loop($cleanup, $storage_conf, $storage, $size, $vmid, $conf, $archive, $password);
136 } else {
10fc3ba5 137 create_rootfs_dir($cleanup, $storage_conf, $storage, $vmid, $conf, $archive, $password);
5b4657d0
DM
138 }
139 } else {
140 die "unable to create containers on storage type '$scfg->{type}'\n";
141 }
142 };
143 if (my $err = $@) {
144 # cleanup
145 File::Path::rmtree($cleanup->{files});
146 foreach my $volid (@{$cleanup->{volids}}) {
147 eval { PVE::Storage::vdisk_free($storage_conf, $volid); };
148 warn $@ if $@;
149 }
150
151 PVE::LXC::destroy_config($vmid);
152
153 die $err;
154 }
155}
156
1571;