Replaces filesystems in /etc/fstab with their new UUIDs.
Signed-off-by: Ben Lipton <[email protected]>
---
instance-p2v-target/fixes/10_fix_fstab | 23 ++++++
instance-p2v-target/fixes/fixlib/fix_fstab.py | 79 ++++++++++++++++++++
instance-p2v-target/test/fix_fstab_test.py | 84 ++++++++++++++++++++++
instance-p2v-target/test/testdata/fstab_uuid_in | 14 ++++
instance-p2v-target/test/testdata/fstab_uuid_out | 14 ++++
5 files changed, 214 insertions(+), 0 deletions(-)
create mode 100755 instance-p2v-target/fixes/10_fix_fstab
create mode 100644 instance-p2v-target/fixes/fixlib/fix_fstab.py
create mode 100755 instance-p2v-target/test/fix_fstab_test.py
create mode 100644 instance-p2v-target/test/testdata/fstab_uuid_in
create mode 100644 instance-p2v-target/test/testdata/fstab_uuid_out
diff --git a/instance-p2v-target/fixes/10_fix_fstab
b/instance-p2v-target/fixes/10_fix_fstab
new file mode 100755
index 0000000..447e3b9
--- /dev/null
+++ b/instance-p2v-target/fixes/10_fix_fstab
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+#
+# Copyright 2011 Google Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+from fixlib import fix_fstab
+
+if __name__ == "__main__":
+ fix_fstab.FixFstab()
diff --git a/instance-p2v-target/fixes/fixlib/fix_fstab.py
b/instance-p2v-target/fixes/fixlib/fix_fstab.py
new file mode 100644
index 0000000..23b7fb8
--- /dev/null
+++ b/instance-p2v-target/fixes/fixlib/fix_fstab.py
@@ -0,0 +1,79 @@
+#!/usr/bin/python
+#
+# Copyright 2011 Google Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+import subprocess
+import re
+
+import fixlib
+
+def FixFstab(fname_in="/target/etc/fstab", fname_out="/target/etc/fstab"):
+ """Alter the fstab to refer to new filesystems.
+
+ This function edits the fstab file found at fname_in, locating the filesystem
+ mounted on / and replacing the device with the string UUID=<new_uuid>.
+
+ @type fname_in: string
+ @param fname_in: The fstab file to read.
+ @type fname_out: string
+ @param fname_out: Where to write the modified file.
+
+ """
+ # TODO(benlipton): This is totally xen-specific, and also assumes a
+ # particular partition layout. We can solve both these problems by making
+ # this script read in a representation of the partition layout, created by
+ # the transfer script, rather than trying to reconstruct/assume it here.
+ uuids = {}
+ fstypes = {}
+ p = subprocess.Popen(["blkid"], stdout=subprocess.PIPE)
+ for line in p.communicate()[0].split('\n'):
+ parts = re.match("/dev/(xvda[0-9]): UUID=\"([-a-z0-9]+)\" TYPE=\"(.+)\"",
+ line)
+ if parts:
+ partname, uuid, fstype = parts.groups()
+ uuids[partname] = uuid
+ fstypes[partname] = fstype
+
+ if "xvda1" not in uuids:
+ print uuids
+ raise fixlib.FixError("Could not determine UUID of root filesystem."
+ " /etc/fstab may need to be edited by hand")
+
+ fstab_file = open(fname_in, "r")
+ new_fstab = ""
+ for line in fstab_file:
+ parts = line.split()
+ if len(parts) >= 2 and parts[0][0] != "#":
+ if parts[1] == "/":
+ parts[0] = "UUID=%s" % uuids["xvda1"]
+ parts[2] = fstypes["xvda1"]
+ line = "\t".join(parts) + "\n"
+ elif parts[2] == "swap":
+ parts[0] = "UUID=%s" % uuids["xvda2"]
+ line = "\t".join(parts) + "\n"
+ new_fstab += line
+ fstab_file.close()
+ fstab_file = open(fname_out, "w")
+ fstab_file.write(new_fstab)
+ fstab_file.close()
+
+def main():
+ FixFstab()
+
+if __name__ == "__main__":
+ main()
diff --git a/instance-p2v-target/test/fix_fstab_test.py
b/instance-p2v-target/test/fix_fstab_test.py
new file mode 100755
index 0000000..0c6ce2a
--- /dev/null
+++ b/instance-p2v-target/test/fix_fstab_test.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+#
+# Copyright 2011 Google Inc. All Rights Reserved.
+
+"""Tests for fix_fstab."""
+
+
+import mox
+import os
+import tempfile
+import unittest
+
+from fixlib import fix_fstab
+
+
+class FixFstabTest(unittest.TestCase):
+ SRCDIR = os.environ.get("SRCDIR", ".")
+ TESTDATA = os.path.join(SRCDIR, "test", "testdata")
+
+ def setUp(self):
+ self.mox = mox.Mox()
+
+ def tearDown(self):
+ self.mox.UnsetStubs()
+ self.mox.ResetAll()
+
+ def testFixFstabReplacesRootLine(self):
+ # stub out blkid call
+ mock_popen = self.mox.CreateMock(fix_fstab.subprocess.Popen)
+
+ self.mox.StubOutWithMock(fix_fstab.subprocess, "Popen",
+ use_mock_anything=True)
+ call = fix_fstab.subprocess.Popen(["blkid"],
+ stdout=fix_fstab.subprocess.PIPE)
+ call.AndReturn(mock_popen)
+ blkid_str = ("/dev/xvda1: UUID=\"11111111-1111-1111-1111-111111111111\""
+ " TYPE=\"ext3\"\n/dev/xvda2: UUID=\"22222222-2222-2222-2222"
+ "-222222222222\" TYPE=\"swap\"\n")
+ mock_popen.communicate().AndReturn((blkid_str, ""))
+
+ self.mox.ReplayAll()
+
+ fname_in = os.path.join(self.TESTDATA, "fstab_uuid_in")
+ handle_out, fname_out = tempfile.mkstemp()
+ os.close(handle_out)
+ fix_fstab.FixFstab(fname_in, fname_out)
+
+ out = open(fname_out, "r")
+ desired = open(os.path.join(self.TESTDATA, "fstab_uuid_out"), "r")
+ out_data = out.read()
+ desired_data = desired.read()
+ out.close()
+ desired.close()
+
+ self.assertEqual(desired_data, out_data)
+
+ self.mox.VerifyAll()
+
+
+ def testFixFstabHandlesDeviceMissing(self):
+ # stub out blkid call
+ mock_popen = self.mox.CreateMock(fix_fstab.subprocess.Popen)
+
+ self.mox.StubOutWithMock(fix_fstab.subprocess, "Popen",
+ use_mock_anything=True)
+ call = fix_fstab.subprocess.Popen(["blkid"],
+ stdout=fix_fstab.subprocess.PIPE)
+ call.AndReturn(mock_popen)
+ mock_popen.communicate().AndReturn(("", ""))
+
+ self.mox.ReplayAll()
+
+ fname_in = os.path.join(self.TESTDATA, "fstab_uuid_in")
+ handle_out, fname_out = tempfile.mkstemp()
+ os.close(handle_out)
+
+ self.assertRaises(fix_fstab.fixlib.FixError, fix_fstab.FixFstab,
+ fname_in, fname_out)
+
+ self.mox.VerifyAll()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/instance-p2v-target/test/testdata/fstab_uuid_in
b/instance-p2v-target/test/testdata/fstab_uuid_in
new file mode 100644
index 0000000..7e02ad6
--- /dev/null
+++ b/instance-p2v-target/test/testdata/fstab_uuid_in
@@ -0,0 +1,14 @@
+# /etc/fstab: static file system information.
+#
+# Use 'blkid' to print the universally unique identifier for a
+# device; this may be used with UUID= as a more robust way to name devices
+# that works even if disks are added and removed. See fstab(5).
+#
+# <file system> <mount point> <type> <options> <dump> <pass>
+proc /proc proc defaults 0 0
+# / was on /dev/sda1 during installation
+UUID=00000000-0000-0000-0000-000000000000 / ext3
errors=remount-ro 0 1
+# swap was on /dev/sda5 during installation
+UUID=55555555-5555-5555-5555-555555555555 none swap sw
0 0
+/dev/scd0 /media/cdrom0 udf,iso9660 user,noauto 0 0
+/dev/fd0 /media/floppy0 auto rw,user,noauto 0 0
diff --git a/instance-p2v-target/test/testdata/fstab_uuid_out
b/instance-p2v-target/test/testdata/fstab_uuid_out
new file mode 100644
index 0000000..d20dbbf
--- /dev/null
+++ b/instance-p2v-target/test/testdata/fstab_uuid_out
@@ -0,0 +1,14 @@
+# /etc/fstab: static file system information.
+#
+# Use 'blkid' to print the universally unique identifier for a
+# device; this may be used with UUID= as a more robust way to name devices
+# that works even if disks are added and removed. See fstab(5).
+#
+# <file system> <mount point> <type> <options> <dump> <pass>
+proc /proc proc defaults 0 0
+# / was on /dev/sda1 during installation
+UUID=11111111-1111-1111-1111-111111111111 / ext3
errors=remount-ro 0 1
+# swap was on /dev/sda5 during installation
+UUID=22222222-2222-2222-2222-222222222222 none swap sw 0 0
+/dev/scd0 /media/cdrom0 udf,iso9660 user,noauto 0 0
+/dev/fd0 /media/floppy0 auto rw,user,noauto 0 0
--
1.7.3.1