home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / UpdateManager / Core / MetaRelease.py < prev    next >
Encoding:
Python Source  |  2009-04-27  |  10.6 KB  |  270 lines

  1. # MetaRelease.py 
  2. #  
  3. #  Copyright (c) 2004,2005 Canonical
  4. #  
  5. #  Author: Michael Vogt <michael.vogt@ubuntu.com>
  6. #  This program is free software; you can redistribute it and/or 
  7. #  modify it under the terms of the GNU General Public License as 
  8. #  published by the Free Software Foundation; either version 2 of the
  9. #  License, or (at your option) any later version.
  10. #  This program is distributed in the hope that it will be useful,
  11. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. #  GNU General Public License for more details.
  14. #  You should have received a copy of the GNU General Public License
  15. #  along with this program; if not, write to the Free Software
  16. #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  17. #  USA
  18.  
  19. import thread
  20. import urllib2
  21. import httplib
  22. import os
  23. import string
  24. import apt_pkg
  25. import time
  26. import sys
  27. import rfc822
  28. from ConfigParser import ConfigParser
  29. from subprocess import Popen,PIPE
  30.  
  31. from utils import *
  32.  
  33. class Dist(object):
  34.     def __init__(self, name, version, date, supported):
  35.         self.name = name
  36.         self.version = version
  37.         self.date = date
  38.         self.supported = supported
  39.         self.releaseNotesURI = None
  40.         self.upgradeTool = None
  41.         self.upgradeToolSig = None
  42.  
  43. class MetaReleaseCore(object):
  44.     """
  45.     A MetaReleaseCore object astracts the list of released 
  46.     distributions. 
  47.     """
  48.  
  49.     DEBUG = "DEBUG_UPDATE_MANAGER" in os.environ
  50.  
  51.     # some constants
  52.     CONF = "/etc/update-manager/release-upgrades"
  53.     CONF_METARELEASE = "/etc/update-manager/meta-release"
  54.  
  55.     def __init__(self, 
  56.                  useDevelopmentRelease=False, 
  57.                  useProposed=False,
  58.                  forceLTS=False):
  59.         self._debug("MetaRelease.__init__() useDevel=%s useProposed=%s" % (useDevelopmentRelease, useProposed))
  60.         # information about the available dists
  61.         self.downloading = True
  62.         self.new_dist = None
  63.         self.current_dist_name = get_dist()
  64.         self.no_longer_supported = None
  65.  
  66.         # default (if the conf file is missing)
  67.         self.METARELEASE_URI = "http://changelogs.ubuntu.com/meta-release"
  68.         self.METARELEASE_URI_LTS = "http://changelogs.ubuntu.com/meta-release-lts"
  69.         self.METARELEASE_URI_UNSTABLE_POSTFIX = "-development"
  70.         self.METARELEASE_URI_PROPOSED_POSTFIX = "-development"
  71.  
  72.         # check the meta-release config first
  73.         parser = ConfigParser()
  74.         if os.path.exists(self.CONF_METARELEASE):
  75.             parser.read(self.CONF_METARELEASE)
  76.             # make changing the metarelease file and the location
  77.             # for the files easy
  78.             if parser.has_section("METARELEASE"):
  79.                 sec = "METARELEASE"
  80.                 for k in ["URI",
  81.                           "URI_LTS",
  82.                           "URI_UNSTABLE_POSTFIX",
  83.                           "URI_PROPOSED_POSTFIX"]:
  84.                     if parser.has_option(sec, k):
  85.                         self._debug("%s: %s " % (self.CONF_METARELEASE,
  86.                                                  parser.get(sec,k)))
  87.                         setattr(self, "%s_%s" % (sec, k), parser.get(sec, k))
  88.  
  89.         # check the config file first to figure if we want lts upgrades only
  90.         parser = ConfigParser()
  91.         if os.path.exists(self.CONF):
  92.             parser.read(self.CONF)
  93.             # now check which specific url to use
  94.             if parser.has_option("DEFAULT","Prompt"):
  95.                 type = parser.get("DEFAULT","Prompt").lower()
  96.                 if (type == "never" or type == "no"):
  97.                     # nothing to do for this object
  98.                     # FIXME: what about no longer supported?
  99.                     self.downloading = False
  100.                     return
  101.                 elif type == "lts":
  102.                     self.METARELEASE_URI = self.METARELEASE_URI_LTS
  103.         # needed for the _tryUpgradeSelf() code in DistUpgradeController
  104.         if forceLTS:
  105.             self.METARELEASE_URI = self.METARELEASE_URI_LTS
  106.         # devel and proposed "just" change the postfix
  107.         if useDevelopmentRelease:
  108.             self.METARELEASE_URI += self.METARELEASE_URI_UNSTABLE_POSTFIX
  109.         elif useProposed:
  110.             self.METARELEASE_URI += self.METARELEASE_URI_PROPOSED_POSTFIX
  111.  
  112.         self._debug("metarelease-uri: %s" % self.METARELEASE_URI)
  113.         self.metarelease_information = None
  114.         if not self._buildMetaReleaseFile():
  115.             self._debug("_buildMetaReleaseFile failed")
  116.             return
  117.         # we start the download thread here and we have a timeout
  118.         t=thread.start_new_thread(self.download, ())
  119.         #t=thread.start_new_thread(self.check, ())
  120.  
  121.     def _buildMetaReleaseFile(self):
  122.         # build the metarelease_file name
  123.         self.METARELEASE_FILE = os.path.join("/var/lib/update-manager/",
  124.                                             os.path.basename(self.METARELEASE_URI))
  125.         # check if we can write to the global location, if not,
  126.         # write to homedir
  127.         try:
  128.             open(self.METARELEASE_FILE,"a")
  129.         except IOError, e:
  130.             path = os.path.expanduser("~/.update-manager-core/")
  131.             if not os.path.exists(path):
  132.         try:
  133.                     os.mkdir(path)
  134.         except OSError, e:
  135.                     sys.stderr.write("mkdir() failed: '%s'" % e)
  136.             return False
  137.             self.METARELEASE_FILE = os.path.join(path,os.path.basename(self.METARELEASE_URI))
  138.         # if it is empty, remove it to avoid I-M-S hits on empty file
  139.         try:
  140.             if os.path.getsize(self.METARELEASE_FILE) == 0:
  141.                 os.unlink(self.METARELEASE_FILE)
  142.         except Exception, e:
  143.             pass
  144.         return True
  145.  
  146.     def dist_no_longer_supported(self, dist):
  147.         """ virtual function that is called when the distro is no longer
  148.             supported
  149.         """
  150.         self.no_longer_supported = dist
  151.     def new_dist_available(self, dist):
  152.         """ virtual function that is called when a new distro release
  153.             is available
  154.         """
  155.         self.new_dist = dist
  156.  
  157.     def parse(self):
  158.         self._debug("MetaRelease.parse()")
  159.         current_dist_name = self.current_dist_name
  160.         self._debug("current dist name: '%s'" % current_dist_name)
  161.         current_dist = None
  162.         dists = []
  163.  
  164.         # parse the metarelease_information file
  165.         index_tag = apt_pkg.ParseTagFile(self.metarelease_information)
  166.         step_result = index_tag.Step()
  167.         while step_result:
  168.             if index_tag.Section.has_key("Dist"):
  169.                 name = index_tag.Section["Dist"]
  170.                 #print name
  171.                 rawdate = index_tag.Section["Date"]
  172.                 date = time.mktime(rfc822.parsedate(rawdate))
  173.                 supported = int(index_tag.Section["Supported"])
  174.                 version = index_tag.Section["Version"]
  175.                 # add the information to a new date object
  176.                 dist = Dist(name, version, date,supported)
  177.                 if index_tag.Section.has_key("ReleaseNotes"):
  178.                     dist.releaseNotesURI = index_tag.Section["ReleaseNotes"]
  179.                 if index_tag.Section.has_key("UpgradeTool"):
  180.                     dist.upgradeTool =  index_tag.Section["UpgradeTool"]
  181.                 if index_tag.Section.has_key("UpgradeToolSignature"):
  182.                     dist.upgradeToolSig =  index_tag.Section["UpgradeToolSignature"]
  183.                 dists.append(dist)
  184.                 if name == current_dist_name:
  185.                     current_dist = dist 
  186.             step_result = index_tag.Step()
  187.  
  188.         # first check if the current runing distro is in the meta-release
  189.         # information. if not, we assume that we run on something not
  190.         # supported and silently return
  191.         if current_dist is None:
  192.             #sys.stderr.write("current dist not found in meta-release file\n")
  193.             return False
  194.  
  195.         # then see what we can upgrade to (only upgrade to supported dists)
  196.         upgradable_to = ""
  197.         for dist in dists:
  198.             if dist.date > current_dist.date and dist.supported == True: 
  199.                 upgradable_to = dist
  200.                 self._debug("new dist: %s" % upgradable_to)
  201.                 break
  202.  
  203.         # only warn if unsupported and a new dist is available (because 
  204.         # the development version is also unsupported)
  205.         if upgradable_to != "" and not current_dist.supported:
  206.             self.dist_no_longer_supported(upgradable_to)
  207.         if upgradable_to != "":
  208.             self.new_dist_available(upgradable_to)
  209.  
  210.         # parsing done and sucessfully
  211.         return True
  212.  
  213.     # the network thread that tries to fetch the meta-index file
  214.     # can't touch the gui, runs as a thread
  215.     def download(self):
  216.         self._debug("MetaRelease.download()")
  217.         lastmodified = 0
  218.         req = urllib2.Request(self.METARELEASE_URI)
  219.         # make sure that we always get the latest file (#107716)
  220.         req.add_header("Cache-Control", "No-Cache")
  221.         req.add_header("Pragma", "no-cache")
  222.         if os.access(self.METARELEASE_FILE, os.W_OK):
  223.             lastmodified = os.stat(self.METARELEASE_FILE).st_mtime
  224.         if lastmodified > 0:
  225.             req.add_header("If-Modified-Since", time.asctime(time.gmtime(lastmodified)))
  226.         try:
  227.             uri=urllib2.urlopen(req)
  228.             # sometime there is a root owned meta-relase file
  229.             # there, try to remove it so that we get it
  230.             # with proper permissions
  231.             if (os.path.exists(self.METARELEASE_FILE) and
  232.                 not os.access(self.METARELEASE_FILE,os.W_OK)):
  233.                 try:
  234.                     os.unlink(self.METARELEASE_FILE)
  235.                 except OSError,e:
  236.                     print "Can't unlink '%s' (%s)" % (self.METARELEASE_FILE,e)
  237.             # we may get excpetion here on e.g. disk full
  238.             try:
  239.                 f=open(self.METARELEASE_FILE,"w+")
  240.                 for line in uri.readlines():
  241.                     f.write(line)
  242.                 f.flush()
  243.                 f.seek(0,0)
  244.                 self.metarelease_information=f
  245.             except IOError, e:
  246.                 pass
  247.             uri.close()
  248.         except (urllib2.URLError, httplib.BadStatusLine), e:
  249.             if os.path.exists(self.METARELEASE_FILE):
  250.                 self.metarelease_information=open(self.METARELEASE_FILE,"r")
  251.         # now check the information we have
  252.         if self.metarelease_information != None:
  253.             self._debug("have self.metarelease_information")
  254.             self.parse()
  255.         else:
  256.             self._debug("NO self.metarelease_information")
  257.         self.downloading = False
  258.  
  259.     def _debug(self, msg):
  260.         if self.DEBUG:
  261.             sys.stderr.write(msg+"\n")
  262.  
  263.  
  264. if __name__ == "__main__":
  265.     meta = MetaReleaseCore(False, False)
  266.     
  267.