[pve-devel] [RFC container 1/2] Setup::Base: more generic ct_modify_file function

Wolfgang Bumiller w.bumiller at proxmox.com
Thu Feb 25 16:26:28 CET 2016


Replaced ct_modify_file_head_portion() with ct_modify_file()
taking a header and and replacing the section in-place
rather than always moving it to the top of the file.

The behavior for when a section is not defined can be
defined via the provided options (replace, prepend, or
append).
---
 src/PVE/LXC/Setup/Base.pm                      | 77 ++++++++++++++++++--------
 src/PVE/LXC/Setup/Redhat.pm                    |  6 +-
 src/PVE/LXC/Setup/SUSE.pm                      |  4 +-
 src/test/test-centos6-001/etc/resolv.conf.exp  |  2 +
 src/test/test-debian-007/etc/resolv.conf       |  2 +
 src/test/test-debian-007/etc/resolv.conf.exp   |  2 +
 src/test/test-debian-008/etc/resolv.conf       |  8 +++
 src/test/test-debian-008/etc/resolv.conf.exp   |  7 +++
 src/test/test-opensuse-001/etc/resolv.conf.exp |  2 +
 9 files changed, 79 insertions(+), 31 deletions(-)
 create mode 100644 src/test/test-debian-007/etc/resolv.conf
 create mode 100644 src/test/test-debian-008/etc/resolv.conf

diff --git a/src/PVE/LXC/Setup/Base.pm b/src/PVE/LXC/Setup/Base.pm
index d84c80e..502a085 100644
--- a/src/PVE/LXC/Setup/Base.pm
+++ b/src/PVE/LXC/Setup/Base.pm
@@ -156,7 +156,7 @@ sub set_dns {
 	$data .= "nameserver $ns\n";
     }
 
-    $self->ct_file_set_contents("/etc/resolv.conf", $data);
+    $self->ct_modify_file("/etc/resolv.conf", 'resolv.conf', $data, replace => 1);
 }
 
 sub set_hostname {
@@ -560,31 +560,62 @@ sub ct_file_set_contents {
     $self->ct_reset_ownership($file);
 }
 
-# Modify a marked portion of a file and move it to the beginning of the file.
-# If the file becomes empty it will be deleted.
-sub ct_modify_file_head_portion {
-    my ($self, $file, $head, $tail, $data) = @_;
-    if ($self->ct_file_exists($file)) {
-	my $old = $self->ct_file_get_contents($file);
-	# remove the portion between $head and $tail (all instances via /g)
-	$old =~ s/(?:^|(?<=\n))\Q$head\E.*\Q$tail\E//gs;
-	chomp $old;
-	if ($old) {
-	    # old data existed, append and add the trailing newline
-	    if ($data) {
-		$self->ct_file_set_contents($file, $head.$data.$tail . $old."\n");
-	    } else {
-		$self->ct_file_set_contents($file, $old."\n");
-	    }
-	} elsif ($data) {
-	    # only our own data will be added
-	    $self->ct_file_set_contents($file, $head.$data.$tail);
+# Modify a marked portion of a file.
+# Optionally if the file becomes empty it will be deleted.
+sub ct_modify_file {
+    my ($self, $file, $header, $data, %options) = @_;
+
+    my $head = "# --- BEGIN PVE $header ---\n";
+    my $tail = "# --- END PVE $header ---\n";
+
+    if (!$self->ct_file_exists($file)) {
+	$self->ct_file_set_contents($file, $head.$data.$tail) if $data;
+	return;
+    }
+
+    my $old = $self->ct_file_get_contents($file);
+    my @lines = split(/\n/, $old);
+
+    my ($beg, $end);
+    foreach my $i (0..(@lines-1)) {
+	my $line = $lines[$i];
+	$beg = $i if !defined($beg) &&
+	    $line =~ /^#\s*---\s*BEGIN\s*PVE\s*\Q$header\E/i;
+	$end = $i if !defined($end) && defined($beg) &&
+	    $line =~ /^#\s*---\s*END\s*PVE\s*\Q$header\E/i;
+	last if defined($beg) && defined($end);
+    }
+
+    if (defined($beg) && defined($end)) {
+	# Found a section
+	if ($data) {
+	    chomp $tail;
+	    splice @lines, $beg, $end-$beg+1, $head.$data.$tail;
 	} else {
-	    # empty => delete
+	    if ($beg == 0 && $end == (@lines-1)) {
+		$self->ct_unlink($file) if $options{delete};
+		return;
+	    }
+	    splice @lines, $beg, $end-$beg+1, $head.$data.$tail;
+	}
+	$self->ct_file_set_contents($file, join("\n", @lines) . "\n");
+    } elsif ($data) {
+	# No section found
+	my $content = join("\n", @lines);
+	chomp $content;
+	if (!$content && !$data && $options{delete}) {
 	    $self->ct_unlink($file);
+	    return;
+	}
+	$content .= "\n";
+	$data = $head.$data.$tail;
+	if ($options{replace}) {
+	    $self->ct_file_set_contents($file, $data);
+	} elsif ($options{prepend}) {
+	    $self->ct_file_set_contents($file, $data . $content);
+	} else { # append
+	    $self->ct_file_set_contents($file, $content . $data);
 	}
-    } else {
-	$self->ct_file_set_contents($file, $head.$data.$tail);
     }
 }
 
diff --git a/src/PVE/LXC/Setup/Redhat.pm b/src/PVE/LXC/Setup/Redhat.pm
index 71cf854..8bc9f16 100644
--- a/src/PVE/LXC/Setup/Redhat.pm
+++ b/src/PVE/LXC/Setup/Redhat.pm
@@ -233,11 +233,7 @@ sub setup_network {
 	next unless $data || $bootproto;
 	$header .= "BOOTPROTO=$bootproto\n";
 	$self->ct_file_set_contents($filename, $header . $data);
-
-	# To keep user-defined routes in route-$iface we mark ours:
-	my $head = "# --- BEGIN PVE ROUTES ---\n";
-	my $tail = "# --- END PVE ROUTES ---\n";
-	$self->ct_modify_file_head_portion($routefile, $head, $tail, $routes);
+	$self->ct_modify_file($routefile, 'ROUTES', $routes, delete => 1, prepend => 1);
     }
 
     my $sysconfig_network = "/etc/sysconfig/network";
diff --git a/src/PVE/LXC/Setup/SUSE.pm b/src/PVE/LXC/Setup/SUSE.pm
index b1be09a..92e2096 100644
--- a/src/PVE/LXC/Setup/SUSE.pm
+++ b/src/PVE/LXC/Setup/SUSE.pm
@@ -123,9 +123,7 @@ sub setup_network {
 	$self->ct_file_set_contents($filename, $data);
 
 	# To keep user-defined routes in route-$iface we mark ours:
-	my $head = "# --- BEGIN PVE ROUTES ---\n";
-	my $tail = "# --- END PVE ROUTES ---\n";
-	$self->ct_modify_file_head_portion($routefile, $head, $tail, $routes);
+	$self->ct_modify_file($routefile, 'ROUTES', $routes, delete => 1, prepend => 1);
     }
 }
 
diff --git a/src/test/test-centos6-001/etc/resolv.conf.exp b/src/test/test-centos6-001/etc/resolv.conf.exp
index e505ad3..f1a268d 100644
--- a/src/test/test-centos6-001/etc/resolv.conf.exp
+++ b/src/test/test-centos6-001/etc/resolv.conf.exp
@@ -1,3 +1,5 @@
+# --- BEGIN PVE resolv.conf ---
 search proxmox.com
 nameserver 8.8.8.8
 nameserver 8.8.8.9
+# --- END PVE resolv.conf ---
diff --git a/src/test/test-debian-007/etc/resolv.conf b/src/test/test-debian-007/etc/resolv.conf
new file mode 100644
index 0000000..75ccbde
--- /dev/null
+++ b/src/test/test-debian-007/etc/resolv.conf
@@ -0,0 +1,2 @@
+# Existing data
+# will be replaced
diff --git a/src/test/test-debian-007/etc/resolv.conf.exp b/src/test/test-debian-007/etc/resolv.conf.exp
index e505ad3..f1a268d 100644
--- a/src/test/test-debian-007/etc/resolv.conf.exp
+++ b/src/test/test-debian-007/etc/resolv.conf.exp
@@ -1,3 +1,5 @@
+# --- BEGIN PVE resolv.conf ---
 search proxmox.com
 nameserver 8.8.8.8
 nameserver 8.8.8.9
+# --- END PVE resolv.conf ---
diff --git a/src/test/test-debian-008/etc/resolv.conf b/src/test/test-debian-008/etc/resolv.conf
new file mode 100644
index 0000000..c3b0e1e
--- /dev/null
+++ b/src/test/test-debian-008/etc/resolv.conf
@@ -0,0 +1,8 @@
+# Existing data
+# Will be kept because there's a PVE section to be replaced
+
+# --- BEGIN PVE resolv.conf ---
+# Stuff gets filled here
+# --- END PVE resolv.conf ---
+
+# This will be kept, too
diff --git a/src/test/test-debian-008/etc/resolv.conf.exp b/src/test/test-debian-008/etc/resolv.conf.exp
index e505ad3..d95c201 100644
--- a/src/test/test-debian-008/etc/resolv.conf.exp
+++ b/src/test/test-debian-008/etc/resolv.conf.exp
@@ -1,3 +1,10 @@
+# Existing data
+# Will be kept because there's a PVE section to be replaced
+
+# --- BEGIN PVE resolv.conf ---
 search proxmox.com
 nameserver 8.8.8.8
 nameserver 8.8.8.9
+# --- END PVE resolv.conf ---
+
+# This will be kept, too
diff --git a/src/test/test-opensuse-001/etc/resolv.conf.exp b/src/test/test-opensuse-001/etc/resolv.conf.exp
index e505ad3..f1a268d 100644
--- a/src/test/test-opensuse-001/etc/resolv.conf.exp
+++ b/src/test/test-opensuse-001/etc/resolv.conf.exp
@@ -1,3 +1,5 @@
+# --- BEGIN PVE resolv.conf ---
 search proxmox.com
 nameserver 8.8.8.8
 nameserver 8.8.8.9
+# --- END PVE resolv.conf ---
-- 
2.1.4





More information about the pve-devel mailing list