Source

vasm / src / vasm / backend / dateset.py

Full commit
#!/usr/bin/env python

#    This file is part of VASM.
#
#    VASM is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License v3 as published by
#    the Free Software Foundation.
#
#    VASM 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 VASM.  If not, see <http://www.gnu.org/licenses/>.



__author__ = "Moises Henriquez"
__author_email__ = "moc.liamg@xnl.E0M"[::-1]


"""Support module for the time/date setting vasm plugin

"""


from datetime import datetime
import utils
import logging
import os

log = logging.getLogger('vasm')

class HWClock(object):
    """ Interact with the hwclock """
    def __init__(self, descriptor = "/etc/hardwareclock"):
        self.descriptor = descriptor

    def _line_sets_value(self, line):
        """ Returns True if line is "localtime" or "UTC" """
        return line.startswith("localtime") or line.startswith("UTC") \
            or line.startswith('LocalTime') or line.startswith('LOCALTIME') \
            or line.startswith("Localtime")

    def get_value(self):
        """ Read self.descriptor and return the current setting """
        ret = ""
        with open(self.descriptor) as f:
            for line in f:
                if self._line_sets_value(line):
                    ret = line.strip()
        # make sure we have a valid setting in there, otherwise, we wont be able
        # to set the value later
        assert ret != "", "Unable to get current hardware clock setting."
        return ret

    def set_value(self, value=""):
        """ Save the provided value to /etc/hardwareclock """
        # Raise exception if value is not valid
        assert value in ("UTC",
                         "LOCALTIME",
            "utc",
            "localtime",
            "Utc",
            "Localtime", 'LocalTime'), "Invalid hardware clock identifier"
        newdata = []
        with open(self.descriptor) as f:
            for line in f:
                if self._line_sets_value(line):
                    line = "%s\n"% value
                newdata.append(line)
        f = open(self.descriptor, 'w')
        f.writelines(''.join(newdata))
        f.close()
        
class TimeZone(object):
    """ Interact with the system timezone settings """
    def __init__(self, zone=None):
        self.zone = zone
        self.tzlink = "/etc/localtime-copied-from"
        self.timezones_base_dir = "/usr/share/zoneinfo/"

    def get_zone(self):
        """ Return a string representing the current timezone """
        # To get the value, we must read /etc/localtime-copied-from.
        # If this excepts, then no timezone is set.
        if os.path.exists(self.tzlink):
            tz = os.readlink(self.tzlink)
            return tz.replace('/usr/share/zoneinfo/', '')
        return 'US/Central'


    def _remove_tz_link(self):
        """ remove the symlink that sets the timezone """
        if os.path.exists(self.tzlink):
            return os.remove(self.tzlink)

    def _check_faulty_rtcports(self):
        """ Check /proc/ioports for unknown rtc ports """
        # This comes from the old vasm scripts.
        # Check for a broken motherboard rtc clock (where ioports for
        # rtc are unknown) to prevent hwclock from causing a hang.
        ret = True
        proc = utils.get_popen(['cat', '/proc/ioports'])
        output = proc.communicate()[0].split("\n")
        for line in output:
            if 'rtc' in line:
                ret = False
                break
        return ret

    def _activate_zone(self):
        """ Active the selected zone """
        if self._check_faulty_rtcports():
            clock_opt = "--directisa"
        else:
            clock_opt = ""
        ctype = HWClock().get_value().lower()
        cm = ['/sbin/hwclock', clock_opt, '--%s'% ctype, '--hctosys']
        proc = utils.get_popen(cm)
        proc.communicate()
        rval = proc.returncode
        return rval > 0

    def set_zone(self, zone=None):
        """ Set the timezone to `zone` """
        assert zone not in ("",None), "Empty values are not allowed for setting the time zone"
        # first we remove the current setting
        self._remove_tz_link()
        
        # we need to create a symlink to /usr/share/zoneinfo
        src = os.path.join(self.timezones_base_dir, zone)
        dest = self.tzlink
        # We need to let this except
        os.symlink(src, dest)
        return self._activate_zone()

    def list_zones(self):
        """ Return a list of time zones to be presented in a UI """
        lst = []

        for zone in os.listdir(self.timezones_base_dir): # level 1
            zonepath = os.path.join(self.timezones_base_dir, zone)
            if os.path.isdir(zonepath): # level 2
                for subzone in os.listdir(zonepath):
                    subzonepath = os.path.join(zonepath, subzone)
                    if os.path.isdir(subzonepath): # level 3
                        for last in os.listdir(subzonepath):
                            lastpath = os.path.join(subzonepath, last)
                            if os.path.isdir(lastpath):
                                for lastzone in os.listdir(lastpath):
                                    lst.append("%s/%s/%s/%s"% ( zone, subzone, last, lastzone))
                            else:
                                lst.append("%s/%s/%s"% (zone,subzone,last))
                    else:
                        lst.append("%s/%s"% (zone,subzone))
            else:
                if not os.path.islink(zone) and '.' not in zone:
                    lst.append(zone)
        lst.sort()
        return lst
        


class DateTime:
    """Manage the system date and time.

    """
    def __init__(self, date_time=None):

        if not date_time:
            date_time = datetime.now()

        self.year = date_time.year
        self.month = date_time.month
        self.day = date_time.day
        self.hour = date_time.hour
        self.minute = date_time.minute
        self.second = date_time.second
        self._date_time = date_time

    def set_date(self):
        """ Set the system date to the values specified.

        """
        if self.month < 10:
            month = "0%s" % self.month
        else:
            month = self.month
            
        if self.day < 10:
            day = "0%s" % self.day
        else:
            day = self.day
            
        datestr = "%s%s%s"% (self.year, month, day)
        cmd = ["/bin/date", "+%Y%m%d", "-s", datestr]
        proc = utils.get_popen(cmd)
        out, err = proc.communicate()
        rcode = proc.returncode

        if rcode > 0:
            _log = ("Command: %s said \"%s\""% (" ".join(cmd),
                    err))
            log.fatal("".join(_log))
            raise DateTimeError(''.join(_log))
        else:
            log.debug("System date has been set to %s"% datestr)        

    def set_time(self):
        """ Set the system time to the specified value

        """
        timestr = "%s:%s:%s" % (self.hour, self.minute, self.second)
        cmd = ["/bin/date", "+%T", "-s", timestr]
        proc = utils.get_popen(cmd)
        out, err = proc.communicate()
        rcode = proc.returncode

        if rcode > 0:
            _log = ("Command: %s said \"%s\""% (" ".join(cmd), err))
            log.fatal(_log)
            raise DateTimeError(''.join(_log))
        else:
            log.debug("System time has been set to %s"% timestr)

    def set_date_and_time(self):
        """Set the system date and time.

        """
        self.set_date()
        self.set_time()

    def set_date_from_tuple(self, data):
        """Update date attributes from a tuple. Convenience method for dealing
        with UI widgets (gtk calendar returns a tuple, for example)
        
        """
        self.year, self.month, self.day = data

    def set_time_from_tuple(self, data):
        """Update time attributes from a tuple. Convenience method for dealing
        with UI widgets (gtk calendar returns a tuple, for example)
        
        """
        self.hour, self.minute, self.second = data


class DateTimeError(Exception):
    """Raised when the system returns an error trying to set time or date

    """
    pass