summaryrefslogtreecommitdiffstats
path: root/yum-presto/presto.py
blob: 48db24db666c344a5301948002fc1bc370257f05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# author: Jonathan Dieter <jdieter@gmail.com>
#
# heavily modified from yum-deltarpm.py created by
#         Lars Herrmann <herrmann@redhat.com>
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2005 Duke University
# Copyright 2007 Jonathan Dieter

from yum.plugins import TYPE_INTERACTIVE, PluginYumExit
from yum import config

import os
import sys

sys.path.append("/usr/share/presto")
import deltarpm
from prestoRepo import PrestoRepository
from prestomdparser import PrestoMDParser
import prestoTransaction
import prestoLog
import prestoDownload

requires_api_version = '2.1'
LOG_FILE = "/var/log/presto.log"
plugin_type = (TYPE_INTERACTIVE,)

rpm_size = 0
drpm_size = 0
drpm_count = 0
log = None

# Configuration stuff
def config_hook(conduit):
    # Set up repository specific deltarpm url and mirrorlist
    config.RepoConf.deltaurl = config.UrlListOption()
    config.RepoConf.deltamirrorlist = config.UrlOption()
    
    # Add --disable-presto option
    parser = conduit.getOptParser()
    parser.add_option('', '--disablepresto', dest='disablepresto',
        action='store_true', default=False,
        help="disable Presto plugin and don't download any deltarpms")
    
# Set up Presto repositories
def postreposetup_hook(conduit):
    opts, commands = conduit.getCmdLine()
    if not opts.disablepresto:
        conduit.info(2, 'Setting up Presto')
        for active_repo in conduit.getRepos().listEnabled():
            p_repo = PrestoRepository(active_repo, conduit)
            p_repo.setup(conduit.getConf().cache)

        conduit.info(2, 'Reading Presto metadata in from local files')
        for active_repo in conduit.getRepos().listEnabled():
            xml = active_repo.p_repo.getPrestoXML()
            if active_repo.p_repo.enabled:
                xmldata = active_repo.p_repo.repoXML.getData('deltas')
                (ctype, csum) = xmldata.checksum
                parser = PrestoMDParser(xml)
                active_repo.p_repo.deltalist = parser.getDeltaList()
    else:
        conduit.info(5, '--disablepresto specified - Presto disabled')
             

def postresolve_hook(conduit):
    global rpm_size
    global drpm_size
    global drpm_count
    
    opts, commands = conduit.getCmdLine()
    if not opts.disablepresto:
        # Cycle through packages to see if there's a deltarpm available
        for newpkg in conduit.getTsInfo():
            if newpkg.ts_state != "e":
                (chosen_drpm, installed, local, drpm_enabled) = prestoTransaction.find_available_drpms(conduit, newpkg)

                # If a drpm was found, change certain package information so it reflects
                # the drpm, not the rpm.
                if chosen_drpm != None:
                    newpkg.po.has_drpm = True
                    conduit.info(2, "Found deltarpm update for %s.%s %s:%s-%s" % (newpkg.name, newpkg.arch, newpkg.epoch, newpkg.version, newpkg.release))
                    # In yum 3.0.x, this doesn't get defined if you run "yum update x" rather than "yum update"
                    rpm_size += int(newpkg.po.size)
                    drpm_size += int(chosen_drpm['size'])
                    newpkg.po.realpackagesize = newpkg.po.size
                    if hasattr(newpkg.po, 'packagesize'):
                        newpkg.po.packagesize = chosen_drpm['size']
                    else:
                        newpkg.po.simple['packagesize'] = chosen_drpm['size']
                    newpkg.po.deltasize = chosen_drpm['size']
                    newpkg.po.deltarelativepath = chosen_drpm['drpm_filename']
                    newpkg.po.deltachecksumtype = chosen_drpm['checksum_type']
                    newpkg.po.deltachecksum = chosen_drpm['checksum']
                    newpkg.po.deltalocalpath = newpkg.po.repo.deltasdir + "/" + os.path.basename(chosen_drpm['drpm_filename'])
                    newpkg.po.to = newpkg
                    newpkg.po.hasdrpm = True
                    newpkg.repoid = newpkg.po.repo.id + " *"
                    drpm_count += 1
                else:
                    if installed and drpm_enabled and not local:
                        try:
                            rpm_size += int(newpkg.po.size)
                            drpm_size += int(newpkg.po.size)
                        except:
                            pass
        return
                        

def predownload_hook(conduit):
    global drpm_count
    global log
    
    # Set up logging
    log = prestoLog.PrestoLog(conduit, LOG_FILE)

    pkglist = conduit.getDownloadPackages()
    
    opts, commands = conduit.getCmdLine()
    if not opts.disablepresto and drpm_count > 0:
        conduit.info(2, "Downloading DeltaRPMs:")
    
        # Download deltarpms
        problems = prestoDownload.downloadPkgs(conduit, pkglist, log)
        
        # If 'exitondownloaderror' is on, exit
        if conduit.confBool('main', 'exitondownloaderror') and len(problems.keys()) > 0:
            errstring = 'Error Downloading Packages:\n'
            for key in problems.keys():
                errors = misc.unique(problems[key])
                for error in errors:
                    errstring += '  %s: %s\n' % (key, error)
            raise PluginYumExit(errstring)
            
        else:
            conduit.info(2, "Downloading RPMs:")

def posttrans_hook(conduit):
    global rpm_size
    global drpm_size
    global log
    
    log.close()
    
    if rpm_size > 0:
        drpm_string = prestoTransaction.format_number(drpm_size)
        rpm_string = prestoTransaction.format_number(rpm_size)
        
        conduit.info(2, "Size of all updates downloaded from Presto-enabled repositories: %s" % drpm_string)
        conduit.info(2, "Size of updates that would have been downloaded if Presto wasn't enabled: %s" % rpm_string)
        conduit.info(2, "This is a savings of %i percent" % (100 - ((drpm_size * 100) / rpm_size)))