Statistics
| Branch: | Tag: | Revision:

root / image_creator / os_type / linux.py @ 9cbb5794

History | View | Annotate | Download (4.3 kB)

1
from image_creator.os_type.unix import Unix
2
import re
3

    
4

    
5
class Linux(Unix):
6
    def __init__(self, rootdev, ghandler):
7
        super(Linux, self).__init__(rootdev, ghandler)
8
        self._uuid = dict()
9
        self._persistent = re.compile('/dev/[hsv]d[a-z][1-9]*')
10

    
11
    def is_persistent(self, dev):
12
        return not self._persistent.match(dev)
13

    
14
    def get_uuid(self, dev):
15
        if dev in self._uuid:
16
            return self._uuid[dev]
17

    
18
        for attr in self.g.blkid(dev):
19
            if attr[0] == 'UUID':
20
                self._uuid[dev] = attr[1]
21
                return attr[1]
22

    
23
    def sysprep(self):
24
        """Prepere system for image creation."""
25
        self.sysprep_acpid()
26
        self.sysprep_persistent_net_rules()
27
        self.sysprep_persistent_devs()
28

    
29
    def sysprep_acpid(self):
30
        """Replace acpid powerdown action scripts to automatically shutdown
31
        the system without checking if a GUI is running.
32
        """
33
        action = '#!/bin/sh\n\nPATH=/sbin:/bin:/usr/bin\n shutdown -h now '
34
        '\"Power button pressed\"'
35

    
36
        if self.g.is_file('/etc/acpi/powerbtn.sh'):
37
            self.g.write(action, '/etc/acpi/powerbtn.sh')
38
        elif self.g.is_file('/etc/acpi/actions/power.sh'):
39
            self.g.write(actions, '/etc/acpi/actions/power.sh')
40
        else:
41
            print "Warning: No acpid action file found"
42

    
43
    def sysprep_persistent_net_rules(self):
44
        """Remove udev rules that will keep network interface names persistent
45
        after hardware changes and reboots. Those rules will be created again
46
        the next time the image runs.
47
        """
48
        rule_file = '/etc/udev/rules.d/70-persistent-net.rules'
49
        if self.g.is_file(rule_file):
50
            self.g.rm(rule_file)
51

    
52
    def sysprep_persistent_devs(self):
53
        """Scan fstab and grub configuration files and replace all
54
        non-persistent device appearences with UUIDs.
55
        """
56
        # convert all devices in fstab to persistent
57
        persistent_root = self._persistent_fstab()
58

    
59
        # convert all devices in grub1 to persistent
60
        self._persistent_grub1(persistent_root)
61

    
62
    def _persistent_grub1(self, new_root):
63
        if self.g.is_file('/boot/grub/menu.lst'):
64
            grub1 = '/boot/grub/menu.lst'
65
        elif self.g.is_file('/etc/grub.conf'):
66
            grub1 = '/etc/grub.conf'
67
        else:
68
            return
69

    
70
        self.g.aug_init('/', 0)
71
        try:
72
            roots = self.g.aug_match('/files%s/title[*]/kernel/root' % grub1)
73
            for root in roots:
74
                dev = self.g.aug_get(root)
75
                if not self.is_persistent(dev):
76
                    # This is not always correct. Grub may contain root entries
77
                    # for other systems, but we only support 1 OS per hard
78
                    # disk, so this shouldn't harm.
79
                    self.g.aug_set(root, new_root)
80
        finally:
81
            self.g.aug_save()
82
            self.g.aug_close()
83

    
84
    def _persistent_fstab(self):
85
        mpoints = self.g.mountpoints()
86
        if len(mpoints) == 0:
87
            pass  # TODO: error handling
88

    
89
        device_dict = dict([[mpoint, dev] for dev, mpoint in mpoints])
90

    
91
        root_dev = None
92
        new_fstab = ""
93
        fstab = self.g.cat('/etc/fstab')
94
        for line in fstab.splitlines():
95

    
96
            line, dev, mpoint = self._convert_fstab_line(line, device_dict)
97
            new_fstab += "%s\n" % line
98

    
99
            if mpoint == '/':
100
                root_dev = dev
101

    
102
        self.g.write('/etc/fstab', new_fstab)
103
        if root_dev is None:
104
            pass  # TODO: error handling
105

    
106
        return root_dev
107

    
108
    def _convert_fstab_line(self, line, devices):
109
        orig = line
110
        line = line.split('#')[0].strip()
111
        if len(line) == 0:
112
            return orig, "", ""
113

    
114
        entry = line.split()
115
        if len(entry) != 6:
116
            print "Warning: detected abnorman entry in fstab"
117
            return orig, "", ""
118

    
119
        dev = entry[0]
120
        mpoint = entry[1]
121

    
122
        if not self.is_persistent(dev):
123
            if mpoint in devices:
124
                dev = "UUID=%s" % self.get_uuid(devices[mpoint])
125
                entry[0] = dev
126
            else:
127
                # comment out the entry
128
                entry[0] = "#%s" % dev
129
            return " ".join(entry), dev, mpoint
130

    
131
        return orig, dev, mpoint
132

    
133
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :