src/checkforupdates.py
author Padraig O'Briain <padraig.obriain@sun.com>
Thu, 25 Feb 2010 13:45:12 +0000
changeset 1791 b2a37ff09e8c
parent 1761 b2d8237ac690
child 1948 2b0682839132
permissions -rw-r--r--
13994 References to package names may need to change

#!/usr/bin/python2.6
# 
# CDDL HEADER START 
# 
# The contents of this file are subject to the terms of the 
# Common Development and Distribution License (the "License").  
# You may not use this file except in compliance with the License.  
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

import os
import sys
import time
import getopt
import gettext
import locale

import pkg.client.progress as progress
import pkg.client.api_errors as api_errors
import pkg.gui.misc_non_gui as nongui_misc
import pkg.gui.enumerations as enumerations
import pkg.misc as misc
from pkg.client import global_settings
from cPickle import UnpicklingError

PKG_CLIENT_NAME = "check_for_updates"
CACHE_VERSION =  2
CACHE_NAME = ".last_refresh_cache"

def __check_for_updates(image_directory, nice):
        if nice:
                os.nice(20)
        global_settings.client_name = PKG_CLIENT_NAME
        pr = progress.NullProgressTracker()

        message = None
        try:
                api_obj = nongui_misc.get_api_object(image_directory, pr)
        except api_errors.VersionException, e:
                message = "Version mismatch: expected version %d, got version %d" % \
                    (e.expected_version, e.received_version)
        except api_errors.ImageNotFoundException, e:
                message = "%s is not an install image" % e.user_dir
        except api_errors.ApiException, e:
                message = "Unexpected exception: %s" % str(e)
        if message != None:
                if debug:
                        print "Failed to get Api object: %s" % message
                return enumerations.UPDATES_UNDETERMINED

        if api_obj == None:
                return enumerations.UPDATES_UNDETERMINED
        ret = __check_last_refresh(api_obj)
        if ret != enumerations.UPDATES_UNDETERMINED:
                return ret
        elif debug:
                print "Updates undetermined in check_last_refresh"

        try:
                stuff_to_do, opensolaris_image = \
                    api_obj.plan_update_all(sys.argv[0],
                    refresh_catalogs = True,
                    noexecute = True, force = True, verbose = False) 
        except api_errors.ApiException, e:
                if debug:
                        print "Exception occurred: ", str(e)
                return enumerations.UPDATES_UNDETERMINED
        if debug:
                print "stuff_to_do: ", stuff_to_do
                print "opensolaris_image: ", opensolaris_image

        __dump_updates_available(api_obj, stuff_to_do)
        if stuff_to_do:
                if debug:
                        print "Updates Available"
                return enumerations.UPDATES_AVAILABLE
        else:
                if debug:
                        print "No updates Available"
                return enumerations.NO_UPDATES_AVAILABLE

def __check_last_refresh(api_obj):
        cache_dir = nongui_misc.get_cache_dir(api_obj)
        if not cache_dir:
                return enumerations.UPDATES_UNDETERMINED
        try:
                info = nongui_misc.read_cache_file(os.path.join(
                    cache_dir, CACHE_NAME + '.cpl'))
                if len(info) == 0:
                        if debug:
                                print "No cache"
                        return enumerations.UPDATES_UNDETERMINED
                if info.get("version") != CACHE_VERSION:
                        if debug:
                                print "Cache version mismatch:", \
                                    info.get("version"), CACHE_VERSION
                        return enumerations.UPDATES_UNDETERMINED
                if info.get("os_release") != os.uname()[2]:
                        if debug:
                                print "OS release mismatch:", \
                                    info.get("os_release"), os.uname()[2]
                        return enumerations.UPDATES_UNDETERMINED
                if info.get("os_version") != os.uname()[3]:
                        if debug:
                                print "OS version mismatch:", \
                                    info.get("os_version"), os.uname()[3]
                        return enumerations.UPDATES_UNDETERMINED
                old_publishers = info.get("publishers")
                count = 0
                for p in api_obj.get_publishers():
                        if p.disabled:
                                continue
                        try:
                                if old_publishers[p.prefix] != p.last_refreshed:
                                        return enumerations.UPDATES_UNDETERMINED
                        except KeyError:
                                return enumerations.UPDATES_UNDETERMINED
                        count += 1

                if count != len(old_publishers):
                        return enumerations.UPDATES_UNDETERMINED
                if info.get("updates_available"):
                        return enumerations.UPDATES_AVAILABLE
                else:
                        return enumerations.NO_UPDATES_AVAILABLE

        except (UnpicklingError, IOError):
                return enumerations.UPDATES_UNDETERMINED

def __dump_updates_available(api_obj, stuff_to_do):
        cache_dir = nongui_misc.get_cache_dir(api_obj)
        if not cache_dir:
                return
        publisher_list = {}
        for p in api_obj.get_publishers():
                if p.disabled:
                        continue
                publisher_list[p.prefix] = p.last_refreshed
        if debug:
                print "publisher_list:", publisher_list
        dump_info = {}
        dump_info["version"] = CACHE_VERSION
        dump_info["os_release"] = os.uname()[2]
        dump_info["os_version"] = os.uname()[3]
        dump_info["updates_available"] = stuff_to_do
        dump_info["publishers"] = publisher_list

        try:
                nongui_misc.dump_cache_file(os.path.join(
                    cache_dir, CACHE_NAME + '.cpl'), dump_info)
        except IOError, e:
                if debug:
                        print "Failed to dump cache: %s" % str(e)

        return

###############################################################################
#-----------------------------------------------------------------------------#
# Main
#-----------------------------------------------------------------------------#

def main(image_directory, nice):
        return __check_for_updates(image_directory, nice)

if __name__ == '__main__':
        misc.setlocale(locale.LC_ALL, "")
        gettext.install("pkg", "/usr/share/locale")
        debug = False
        set_nice = False
        try:
                opts, pargs = getopt.getopt(sys.argv[1:], "n", ["nice"])
        except getopt.GetoptError, ex:
                print "Usage: illegal option -- %s" % ex.opt
                sys.exit(enumerations.UPDATES_UNDETERMINED)
        if len(pargs) != 1:
                print "Usage: One argument, image directory must be specified"
                sys.exit(enumerations.UPDATES_UNDETERMINED)
        image_dir = pargs[0]
        for opt, args in opts:
                if debug:
                        print "opt: ", opt
                        print "args: ", args
                if opt in ( "-n", "--nice"):
                        set_nice = True
        if debug:
                print "Start check_for_updates for: ", image_dir, set_nice
                a = time.time()
        return_value = main(image_dir, set_nice)
        if debug:
                print "time taken: ", time.time() - a
        sys.exit(return_value)