this patch recovers the config form the tarball.
It will nt recover the nework setting if you recover from OVZ
---
 src/PVE/API2/LXC.pm          |  30 +++-
 src/PVE/LXCCreate.pm         | 105 +++++++++++---
 src/PVE/VZDump/ConvertOVZ.pm | 319 +++++++++++++++++++++++++++++++++++++++++++
 src/PVE/VZDump/Makefile      |   1 +
 4 files changed, 432 insertions(+), 23 deletions(-)
 create mode 100644 src/PVE/VZDump/ConvertOVZ.pm

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 9e82bc4..d4e8936 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -185,7 +185,7 @@ __PACKAGE__->register_method({
            # fixme: limit allowed parameters
 
        }
-       
+
        my $force = extract_param($param, 'force');
 
        if (!($same_container_exists && $restore && $force)) {
@@ -241,10 +241,23 @@ __PACKAGE__->register_method({
        }
 
        my $conf = {};
+       if ($restore) {
+           $conf = PVE::LXCCreate::recover_config($archive, $conf);
 
-       $param->{hostname} ||= "CT$vmid";
-       $param->{memory} ||= 512;
-       $param->{swap} = 512 if !defined($param->{swap});
+           foreach my $item ( %{$conf}) {
+
+               if ($item =~ m/(net\d+)/) {
+                   my $net = $1;
+                   my $pair = $conf->{$net}->{'veth.pair'};
+                   $pair =~ s/\d+/$vmid/;
+                   $conf->{$net}->{'veth.pair'} = $pair;
+               };
+           }
+       }
+
+       $param->{hostname} ||= "CT$vmid" if !defined($conf->{'lxc.utsname'});
+       $param->{memory} ||= 512 if 
!defined($conf->{'lxc.cgroup.memory.limit_in_bytes'});
+       $param->{swap} = 512 if (!defined($param->{swap}) && 
!defined($conf->{'lxc.cgroup.memory.memsw.limit_in_bytes'}));
 
        PVE::LXC::update_lxc_config($vmid, $conf, 0, $param);
 
@@ -268,9 +281,14 @@ __PACKAGE__->register_method({
                PVE::Cluster::check_vmid_unused($vmid);
            }
        };
-       
+
        my $code = sub {
-           
+           if ($restore && ($ostemplate =~ m/openvz/) ) {
+               print 
"###########################################################\n";
+               print "Restore from OpenVZ please check the config and add 
network\n";
+               print 
"###########################################################\n";
+           }
+
            &$check_vmid_usage(); # final check after locking
 
            PVE::Cluster::check_cfs_quorum();
diff --git a/src/PVE/LXCCreate.pm b/src/PVE/LXCCreate.pm
index 91851ee..99521af 100644
--- a/src/PVE/LXCCreate.pm
+++ b/src/PVE/LXCCreate.pm
@@ -9,6 +9,7 @@ use Data::Dumper;
 use PVE::Storage;
 use PVE::LXC;
 use PVE::LXCSetup;
+use PVE::VZDump::ConvertOVZ;
 
 sub next_free_nbd_dev {
     
@@ -51,7 +52,7 @@ sub restore_archive {
    } else {
        print "extracting archive '$archive'\n";
        PVE::Tools::run_command($cmd);
-    }
+   }
     
     # is this really required? what for?
     #$cmd = [@$userns_cmd, 'mkdir', '-p', "$rootdir/dev/pts"];
@@ -74,23 +75,93 @@ sub restore_archive {
     });
 }
 
+my $openvz_to_lxc = sub {
+    my ($openvz_conf) = @_;
+
+    my $conf = {};
+
+    return $conf;
+};
+
+sub tar_archive_search_conf {
+    my ($archive) = @_;
+
+    die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
+
+    my $pid = open(my $fh, '-|', 'tar', 'tf', $archive) ||
+       die "unable to open file '$archive'\n";
+
+    my $file;
+    while ($file = <$fh>) {
+       last if ($file =~ m/.*(vps.conf|lxc.conf)/);
+    }
+
+    kill 15, $pid;
+    waitpid $pid, 0;
+    close $fh;
+
+    die "ERROR: archive contaions no config\n" if !$file;
+    chomp $file;
+
+    return $file;
+}
+
+sub recover_config {
+    my ($archive, $conf) = @_;
+
+    my $conf_file = tar_archive_search_conf($archive);
+
+    #untainting var
+    $conf_file =~ m/(etc\/vzdump\/(lxc\.conf|vps\.conf))/;
+    $conf_file = "./$1";
+
+    my ($old_vmid) = $archive =~ /-(\d+)-/;
+
+    my $raw = '';
+    my $out = sub {
+       my $output = shift;
+       $raw .= "$output\n";
+    };
+
+    PVE::Tools::run_command(['tar', '-xpOf', $archive, $conf_file, 
'--occurrence'], outfunc => $out);
+
+    $conf = undef;
+
+    if ($conf_file =~ m/lxc.conf/) {
+
+           $conf = PVE::LXC::parse_lxc_config("/lxc/$old_vmid/config" , $raw);
+
+           delete $conf->{'pve.volid'};
+           delete $conf->{'lxc.rootfs'};
+           delete $conf->{snapshots};
+
+    } elsif ($conf_file =~ m/vps.conf/) {
+
+       $conf = PVE::VZDump::ConvertOVZ::convert_ovz($raw);
+
+    }
+
+    return $conf;
+}
+
 sub restore_and_configure {
-    my ($vmid, $archive, $rootdir, $conf, $password) = @_;
+    my ($vmid, $archive, $rootdir, $conf, $password, $restore) = @_;
 
     restore_archive($archive, $rootdir, $conf);
 
     PVE::LXC::write_config($vmid, $conf);
 
-    my $lxc_setup = PVE::LXCSetup->new($conf, $rootdir); # detect OS
+    if (!$restore) {
+       my $lxc_setup = PVE::LXCSetup->new($conf, $rootdir); # detect OS
 
-    PVE::LXC::write_config($vmid, $conf); # safe config (after OS detection)
-
-    $lxc_setup->post_create_hook($password);
+       PVE::LXC::write_config($vmid, $conf); # safe config (after OS detection)
+       $lxc_setup->post_create_hook($password);
+    }
 }
 
 # directly use a storage directory
 sub create_rootfs_dir {
-    my ($cleanup, $storage_conf, $storage, $vmid, $conf, $archive, $password) 
= @_;
+    my ($cleanup, $storage_conf, $storage, $vmid, $conf, $archive, $password, 
$restore) = @_;
 
     # note: there is no size limit
     $conf->{'pve.disksize'} = 0;
@@ -101,12 +172,12 @@ sub create_rootfs_dir {
     push @{$cleanup->{files}}, $private;
     $conf->{'lxc.rootfs'} = $private;
 
-    restore_and_configure($vmid, $archive, $private, $conf, $password);
+    restore_and_configure($vmid, $archive, $private, $conf, $password, 
$restore);
 }
 
 # use new subvolume API
 sub create_rootfs_subvol {
-    my ($cleanup, $storage_conf, $storage, $size, $vmid, $conf, $archive, 
$password) = @_;
+    my ($cleanup, $storage_conf, $storage, $size, $vmid, $conf, $archive, 
$password, $restore) = @_;
 
     my $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 
'subvol', 
                                          "subvol-$vmid-rootfs", $size);
@@ -118,12 +189,12 @@ sub create_rootfs_subvol {
     $conf->{'lxc.rootfs'} = $private;
     $conf->{'pve.volid'} = $volid;
 
-    restore_and_configure($vmid, $archive, $private, $conf, $password);
+    restore_and_configure($vmid, $archive, $private, $conf, $password, 
$restore);
 }
 
 # create a raw file, then loop mount
 sub create_rootfs_dir_loop {
-    my ($cleanup, $storage_conf, $storage, $size, $vmid, $conf, $archive, 
$password) = @_;
+    my ($cleanup, $storage_conf, $storage, $size, $vmid, $conf, $archive, 
$password, $restore) = @_;
 
     my $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 
'raw', "vm-$vmid-rootfs.raw", $size);
     $conf->{'pve.disksize'} = $size/(1024*1024);
@@ -154,7 +225,7 @@ sub create_rootfs_dir_loop {
        $mountpoint = $tmp;
 
        $conf->{'pve.volid'} = $volid;
-       restore_and_configure($vmid, $archive, $mountpoint, $conf, $password);
+       restore_and_configure($vmid, $archive, $mountpoint, $conf, $password, 
$restore);
     };
     if (my $err = $@) {
        if ($mountpoint) {
@@ -172,7 +243,7 @@ sub create_rootfs_dir_loop {
 
 # create a file, then mount with qemu-nbd
 sub create_rootfs_dir_qemu {
-    my ($cleanup, $storage_conf, $storage, $size, $vmid, $conf, $archive, 
$password) = @_;
+    my ($cleanup, $storage_conf, $storage, $size, $vmid, $conf, $archive, 
$password, $restore) = @_;
 
     my $format = 'qcow2';
     
@@ -205,7 +276,7 @@ sub create_rootfs_dir_qemu {
        $mountpoint = $tmp;
 
        $conf->{'pve.volid'} = $volid;
-       restore_and_configure($vmid, $archive, $mountpoint, $conf, $password);
+       restore_and_configure($vmid, $archive, $mountpoint, $conf, $password, 
$restore);
     };
     if (my $err = $@) {
        if ($mountpoint) {
@@ -263,14 +334,14 @@ sub create_rootfs {
        my $scfg = PVE::Storage::storage_config($storage_conf, $storage);
        if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs') {
            if ($size > 0) {
-               create_rootfs_dir_loop($cleanup, $storage_conf, $storage, 
$size, $vmid, $conf, $archive, $password);
+               create_rootfs_dir_loop($cleanup, $storage_conf, $storage, 
$size, $vmid, $conf, $archive, $password, $restore);
            } else {
-               create_rootfs_dir($cleanup, $storage_conf, $storage, $vmid, 
$conf, $archive, $password);
+               create_rootfs_dir($cleanup, $storage_conf, $storage, $vmid, 
$conf, $archive, $password, $restore);
            }
        } elsif ($scfg->{type} eq 'zfspool') {
 
            create_rootfs_subvol($cleanup, $storage_conf, $storage, $size, 
-                                $vmid, $conf, $archive, $password);
+                                $vmid, $conf, $archive, $password, $restore);
            
        } else {
            
diff --git a/src/PVE/VZDump/ConvertOVZ.pm b/src/PVE/VZDump/ConvertOVZ.pm
new file mode 100644
index 0000000..85f747a
--- /dev/null
+++ b/src/PVE/VZDump/ConvertOVZ.pm
@@ -0,0 +1,319 @@
+package PVE::VZDump::ConvertOVZ;
+
+use strict;
+use warnings;
+use POSIX qw (LONG_MAX);
+
+my $res_unlimited = LONG_MAX;
+
+sub ovz_config_extract_mem_swap {
+    my ($veconf, $unit) = @_;
+
+    $unit = 1 if !$unit;
+
+    my ($mem, $swap) = (int((512*1024*1024 + $unit - 1)/$unit), 0);
+
+    my $maxpages = ($res_unlimited / 4096);
+
+    if ($veconf->{swappages}) {
+       if ($veconf->{physpages} && $veconf->{physpages}->{lim} &&
+           ($veconf->{physpages}->{lim} < $maxpages)) {
+           $mem = int(($veconf->{physpages}->{lim} * 4096 + $unit - 1) / 
$unit);
+       }
+       if ($veconf->{swappages}->{lim} && ($veconf->{swappages}->{lim} < 
$maxpages)) {
+           $swap = int (($veconf->{swappages}->{lim} * 4096 + $unit - 1) / 
$unit);
+       }
+    } else {
+       if ($veconf->{vmguarpages} && $veconf->{vmguarpages}->{bar} &&
+           ($veconf->{vmguarpages}->{bar} < $maxpages)) {
+           $mem = int(($veconf->{vmguarpages}->{bar} * 4096 + $unit - 1) / 
$unit);
+       }
+    }
+
+    return ($mem, $swap);
+}
+
+sub parse_res_num_ignore {
+    my ($key, $text) = @_;
+
+    if ($text =~ m/^(\d+|unlimited)(:.*)?$/) {
+       return { bar => $1 eq 'unlimited' ? $res_unlimited : $1 };
+    }
+
+    return undef;
+}
+
+sub parse_res_num_num {
+    my ($key, $text) = @_;
+
+    if ($text =~ m/^(\d+|unlimited)(:(\d+|unlimited))?$/) {
+       my $res = { bar => $1 eq 'unlimited' ? $res_unlimited : $1 };
+       if (defined($3)) {
+           $res->{lim} = $3 eq 'unlimited' ? $res_unlimited : $3;
+       } else {
+           $res->{lim} = $res->{bar};
+       }
+       return $res;
+    }
+
+    return undef;
+}
+
+sub parse_res_bar_limit {
+    my ($text, $base) = @_;
+
+    return $res_unlimited if $text eq 'unlimited';
+
+    if ($text =~ m/^(\d+)([TGMKP])?$/i) {
+       my $val = $1;
+       my $mult = $2 ? lc($2) : '';
+       if ($mult eq 'k') {
+           $val = $val * 1024;
+       } elsif ($mult eq 'm') {
+           $val = $val * 1024 * 1024;
+       } elsif ($mult eq 'g') {
+           $val = $val * 1024 * 1024 * 1024;
+       } elsif ($mult eq 't') {
+           $val = $val * 1024 * 1024 * 1024 * 1024;
+       } elsif ($mult eq 'p') {
+           $val = $val * 4096;
+       } else {
+           return $val;
+       }
+       return int($val/$base);
+    }
+
+    return undef;
+}
+
+sub parse_res_bytes_bytes {
+    my ($key, $text) = @_;
+
+    my @a = split(/:/, $text);
+    $a[1] = $a[0] if !defined($a[1]);
+
+    my $bar = parse_res_bar_limit($a[0], 1);
+    my $lim = parse_res_bar_limit($a[1], 1);
+
+    if (defined($bar) && defined($lim)) {
+       return { bar => $bar, lim => $lim };
+    }
+
+    return undef;
+}
+
+sub parse_res_block_block {
+    my ($key, $text) = @_;
+
+    my @a = split(/:/, $text);
+    $a[1] = $a[0] if !defined($a[1]);
+
+    my $bar = parse_res_bar_limit($a[0], 1024);
+    my $lim = parse_res_bar_limit($a[1], 1024);
+
+    if (defined($bar) && defined($lim)) {
+       return { bar => $bar, lim => $lim };
+    }
+
+    return undef;
+}
+
+sub parse_res_pages_pages {
+    my ($key, $text) = @_;
+
+    my @a = split(/:/, $text);
+    $a[1] = $a[0] if !defined($a[1]);
+
+    my $bar = parse_res_bar_limit($a[0], 4096);
+    my $lim = parse_res_bar_limit($a[1], 4096);
+
+    if (defined($bar) && defined($lim)) {
+       return { bar => $bar, lim => $lim };
+    }
+
+    return undef;
+}
+
+sub parse_res_pages_unlimited {
+    my ($key, $text) = @_;
+
+    my @a = split(/:/, $text);
+
+    my $bar = parse_res_bar_limit($a[0], 4096);
+
+    if (defined($bar)) {
+       return { bar => $bar, lim => $res_unlimited };
+    }
+
+    return undef;
+}
+
+sub parse_res_pages_ignore {
+    my ($key, $text) = @_;
+
+    my @a = split(/:/, $text);
+
+    my $bar = parse_res_bar_limit($a[0], 4096);
+
+    if (defined($bar)) {
+       return { bar => $bar };
+    }
+
+    return undef;
+}
+
+sub parse_res_ignore_pages {
+    my ($key, $text) = @_;
+
+    my @a = split(/:/, $text);
+    $a[1] = $a[0] if !defined($a[1]);
+
+    my $lim = parse_res_bar_limit($a[1] , 4096);
+
+    if (defined($lim)) {
+       return { bar => 0, lim => $lim };
+    }
+
+    return undef;
+}
+
+sub parse_boolean {
+    my ($key, $text) = @_;
+
+    return { value => 1 } if $text =~ m/^(yes|true|on|1)$/i;
+    return { value => 0 } if $text =~ m/^(no|false|off|0)$/i;
+
+    return undef;
+};
+
+sub parse_integer {
+    my ($key, $text) = @_;
+
+    if ($text =~ m/^(\d+)$/) {
+       return { value => int($1) };
+    }
+
+    return undef;
+};
+
+my $ovz_ressources = {
+    numproc => \&parse_res_num_ignore,
+    numtcpsock => \&parse_res_num_ignore,
+    numothersock => \&parse_res_num_ignore,
+    numfile => \&parse_res_num_ignore,
+    numflock => \&parse_res_num_num,
+    numpty => \&parse_res_num_ignore,
+    numsiginfo => \&parse_res_num_ignore,
+    numiptent => \&parse_res_num_ignore,
+
+    vmguarpages => \&parse_res_pages_unlimited,
+    oomguarpages => \&parse_res_pages_unlimited,
+    lockedpages => \&parse_res_pages_ignore,
+    privvmpages => \&parse_res_pages_pages,
+    shmpages => \&parse_res_pages_ignore,
+    physpages => \&parse_res_pages_pages,
+    swappages => \&parse_res_ignore_pages,
+
+    kmemsize => \&parse_res_bytes_bytes,
+    tcpsndbuf => \&parse_res_bytes_bytes,
+    tcprcvbuf => \&parse_res_bytes_bytes,
+    othersockbuf => \&parse_res_bytes_bytes,
+    dgramrcvbuf => \&parse_res_bytes_bytes,
+    dcachesize => \&parse_res_bytes_bytes,
+
+    disk_quota => \&parse_boolean,
+    diskspace => \&parse_res_block_block,
+    diskinodes => \&parse_res_num_num,
+    quotatime => \&parse_integer,
+    quotaugidlimit => \&parse_integer,
+
+    cpuunits => \&parse_integer,
+    cpulimit => \&parse_integer,
+    cpus => \&parse_integer,
+    cpumask => 'string',
+    meminfo => 'string',
+    iptables => 'string',
+
+    ip_address => 'string',
+    netif => 'string',
+    hostname => 'string',
+    nameserver => 'string',
+    searchdomain => 'string',
+
+    name => 'string',
+    description => 'string',
+    onboot => \&parse_boolean,
+    initlog => \&parse_boolean,
+    bootorder => \&parse_integer,
+    ostemplate => 'string',
+    ve_root => 'string',
+    ve_private => 'string',
+    disabled => \&parse_boolean,
+    origin_sample => 'string',
+    noatime => \&parse_boolean,
+    capability => 'string',
+    devnodes => 'string',
+    devices => 'string',
+    pci => 'string',
+    features => 'string',
+    ioprio => \&parse_integer,
+
+};
+
+my $parse_ovz_config = sub {
+    my ($raw) = @_;
+
+    my $data = {};
+
+    return undef if !defined($raw);
+
+    while ($raw && $raw =~ /^(.*?)(\n|$)/mg) {
+       my $line = $1;
+
+       next if $line =~ m/^\#/;
+       next if $line =~ m/^\s*$/;
+
+       if ($line =~ m/^\s*([A-Z][A-Z0-9_]*)\s*=\s*\"(.*)\"\s*$/i) {
+           my $name = lc($1);
+           my $text = $2;
+           my $parser = $ovz_ressources->{$name};
+           if (!$parser || !ref($parser)) {
+               $data->{$name}->{value} = $text;
+               next;
+           } else {
+               if (my $res = &$parser($name, $text)) {
+                   $data->{$name} = $res;
+                   next;
+               }
+           }
+       }
+       die "unable to parse config line: $line\n";
+    }
+
+    return $data;
+};
+
+sub convert_ovz {
+   my ($raw) = @_;
+
+   my $conf = {};
+
+   my $ovz_conf = &$parse_ovz_config($raw);
+
+   $conf->{'pve.disksize'} = $ovz_conf->{'diskspace'}->{'bar'} / 1024 / 1024;
+
+   my ($mem, $swap) = ovz_config_extract_mem_swap($ovz_conf, 0);
+
+   $conf->{'lxc.cgroup.memory.limit_in_bytes'} = $mem;
+
+   $conf->{'lxc.cgroup.memory.memsw.limit_in_bytes'} = ($swap + $mem);
+
+   $conf->{'lxc.cgroup.cpu.shares'} = 1024;
+
+   $conf->{'lxc.cgroup.cpu.cfs_quota_us'} = $ovz_conf->{cpus}->{value} * 
100000;
+   $conf->{'lxc.cgroup.cpu.cfs_period_us'} = 100000;
+
+   $conf->{'lxc.utsname'} = $ovz_conf->{hostname}->{value};
+
+   return $conf;
+}
diff --git a/src/PVE/VZDump/Makefile b/src/PVE/VZDump/Makefile
index 8f66c90..4e35dcd 100644
--- a/src/PVE/VZDump/Makefile
+++ b/src/PVE/VZDump/Makefile
@@ -2,3 +2,4 @@
 .PHONY: install
 install:
        install -D -m 0644 LXC.pm ${PERLDIR}/PVE/VZDump/LXC.pm
+       install -D -m 0644 ConvertOVZ.pm ${PERLDIR}/PVE/VZDump/ConvertOVZ.pm
-- 
2.1.4


_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to