X-Git-Url: https://code.grnet.gr/git/snf-image-creator/blobdiff_plain/71b0ab283eeef37c3d3ecd98fbafa6eaa50b58d8..121f3bc0cf7fc8591c01e21dc686e07c685ef23a:/image_creator/os_type/linux.py diff --git a/image_creator/os_type/linux.py b/image_creator/os_type/linux.py index 5a3d29d..4724336 100644 --- a/image_creator/os_type/linux.py +++ b/image_creator/os_type/linux.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +# # Copyright 2012 GRNET S.A. All rights reserved. # # Redistribution and use in source and binary forms, with or @@ -31,6 +33,8 @@ # interpreted as representing official policies, either expressed # or implied, of GRNET S.A. +"""This module hosts OS-specific code for Linux""" + from image_creator.os_type.unix import Unix, sysprep import re @@ -44,46 +48,6 @@ class Linux(Unix): self._uuid = dict() self._persistent = re.compile('/dev/[hsv]d[a-z][1-9]*') - def _do_collect_metadata(self): - """Collect metadata about the OS""" - - super(Linux, self)._do_collect_metadata() - self.meta["USERS"] = " ".join(self._get_passworded_users()) - - # Delete the USERS metadata if empty - if not len(self.meta['USERS']): - self.out.warn("No passworded users found!") - del self.meta['USERS'] - - def _get_passworded_users(self): - users = [] - regexp = re.compile('(\S+):((?:!\S+)|(?:[^!*]\S+)|):(?:\S*:){6}') - - for line in self.g.cat('/etc/shadow').splitlines(): - match = regexp.match(line) - if not match: - continue - - user, passwd = match.groups() - if len(passwd) > 0 and passwd[0] == '!': - self.out.warn("Ignoring locked %s account." % user) - else: - users.append(user) - - return users - - def is_persistent(self, dev): - return not self._persistent.match(dev) - - def get_uuid(self, dev): - if dev in self._uuid: - return self._uuid[dev] - - uuid = self.g.vfs_uuid(dev) - assert len(uuid) - self._uuid[dev] = uuid - return uuid - @sysprep(enabled=False) def remove_user_accounts(self, print_header=True): """Remove all user accounts with id greater than 1000""" @@ -179,21 +143,21 @@ class Linux(Unix): event_exp = re.compile('event=(.+)', re.I) action_exp = re.compile('action=(.+)', re.I) - for f in self.g.readdir(events_dir): - if f['ftyp'] != 'r': + for events_file in self.g.readdir(events_dir): + if events_file['ftyp'] != 'r': continue - fullpath = "%s/%s" % (events_dir, f['name']) + fullpath = "%s/%s" % (events_dir, events_file['name']) event = "" action = "" for line in self.g.cat(fullpath).splitlines(): - m = event_exp.match(line) - if m: - event = m.group(1) + match = event_exp.match(line) + if match: + event = match.group(1) continue - m = action_exp.match(line) - if m: - action = m.group(1) + match = action_exp.match(line) + if match: + action = match.group(1) continue if event.strip() in ("button[ /]power", "button/power.*"): @@ -275,6 +239,9 @@ class Linux(Unix): self._persistent_grub1(persistent_root) def _persistent_grub1(self, new_root): + """Replaces non-persistent device name occurencies with persistent + ones in GRUB1 configuration files. + """ if self.g.is_file('/boot/grub/menu.lst'): grub1 = '/boot/grub/menu.lst' elif self.g.is_file('/etc/grub.conf'): @@ -287,7 +254,7 @@ class Linux(Unix): roots = self.g.aug_match('/files%s/title[*]/kernel/root' % grub1) for root in roots: dev = self.g.aug_get(root) - if not self.is_persistent(dev): + if not self._is_persistent(dev): # This is not always correct. Grub may contain root entries # for other systems, but we only support 1 OS per hard # disk, so this shouldn't harm. @@ -297,6 +264,9 @@ class Linux(Unix): self.g.aug_close() def _persistent_fstab(self): + """Replaces non-persistent device name occurencies in /etc/fstab with + persistent ones. + """ mpoints = self.g.mountpoints() if len(mpoints) == 0: pass # TODO: error handling @@ -321,6 +291,9 @@ class Linux(Unix): return root_dev def _convert_fstab_line(self, line, devices): + """Replace non-persistent device names in an fstab line to their UUID + equivalent + """ orig = line line = line.split('#')[0].strip() if len(line) == 0: @@ -334,9 +307,9 @@ class Linux(Unix): dev = entry[0] mpoint = entry[1] - if not self.is_persistent(dev): + if not self._is_persistent(dev): if mpoint in devices: - dev = "UUID=%s" % self.get_uuid(devices[mpoint]) + dev = "UUID=%s" % self._get_uuid(devices[mpoint]) entry[0] = dev else: # comment out the entry @@ -345,4 +318,46 @@ class Linux(Unix): return orig, dev, mpoint + def _do_collect_metadata(self): + """Collect metadata about the OS""" + super(Linux, self)._do_collect_metadata() + self.meta["USERS"] = " ".join(self._get_passworded_users()) + + # Delete the USERS metadata if empty + if not len(self.meta['USERS']): + self.out.warn("No passworded users found!") + del self.meta['USERS'] + + def _get_passworded_users(self): + """Returns a list of non-locked user accounts""" + users = [] + regexp = re.compile('(\S+):((?:!\S+)|(?:[^!*]\S+)|):(?:\S*:){6}') + + for line in self.g.cat('/etc/shadow').splitlines(): + match = regexp.match(line) + if not match: + continue + + user, passwd = match.groups() + if len(passwd) > 0 and passwd[0] == '!': + self.out.warn("Ignoring locked %s account." % user) + else: + users.append(user) + + return users + + def _is_persistent(self, dev): + """Checks if a device name is persistent.""" + return not self._persistent.match(dev) + + def _get_uuid(self, dev): + """Returns the UUID corresponding to a device""" + if dev in self._uuid: + return self._uuid[dev] + + uuid = self.g.vfs_uuid(dev) + assert len(uuid) + self._uuid[dev] = uuid + return uuid + # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :