~launchpad-pqm/launchpad/devel

12561.1.6 by Curtis Hovey
Updated copyrights.
1
# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
8687.15.17 by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/.
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
4983.1.2 by Curtis Hovey
Added pylint exceptions to database classes.
4
# pylint: disable-msg=E0611,W0212
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
5
6
"""Module docstring goes here."""
7
8
__metaclass__ = type
12192.2.3 by j.c.sackett
Storm changes and some reformatting.
9
__all__ = [
10
    'DistributionMirror',
11
    'MirrorDistroArchSeries',
12
    'MirrorDistroSeriesSource',
13
    'MirrorProbeRecord',
14
    'DistributionMirrorSet',
15
    'MirrorCDImageDistroSeries',
16
    ]
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
17
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
18
from datetime import (
19
    datetime,
20
    MINYEAR,
21
    timedelta,
22
    )
23
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
24
import pytz
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
25
from sqlobject import (
26
    BoolCol,
27
    ForeignKey,
28
    StringCol,
29
    )
30
from sqlobject.sqlbuilder import AND
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
31
from storm.store import Store
32
from storm.expr import (
33
    And,
34
    Desc,
35
    Func,
36
    )
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
37
from zope.component import getUtility
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
38
from zope.interface import implements
39
2908.4.19 by Guilherme Salgado
Fixed last issues, improved tests and make it possible for mirror owners to download the log file.
40
from canonical.config import config
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
41
from canonical.database.constants import UTC_NOW
42
from canonical.database.datetimecol import UtcDateTimeCol
3691.373.5 by Christian Reis
Move DBSchema and Item into webapp.enum, and put EnumCol into canonical.database.enumcol
43
from canonical.database.enumcol import EnumCol
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
44
from canonical.database.sqlbase import (
45
    SQLBase,
46
    sqlvalues,
47
    )
48
from canonical.launchpad.helpers import (
49
    get_contact_email_addresses,
50
    get_email_template,
51
    shortlist,
52
    )
53
from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
10739.1.11 by Jonathan Davies
Use IStore instead of SQLBase for MirrorDistroArchSeries and
54
from canonical.launchpad.interfaces.lpstorm import IStore
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
55
from canonical.launchpad.mail import (
56
    format_address,
57
    simple_sendmail,
58
    )
59
from canonical.launchpad.webapp import (
60
    canonical_url,
61
    urlappend,
62
    )
63
from canonical.launchpad.webapp.interfaces import (
64
    DEFAULT_FLAVOR,
65
    IStoreSelector,
66
    MAIN_STORE,
67
    )
68
from lp.archivepublisher.diskpool import poolify
11637.3.12 by j.c.sackett
Fixed CannotTranstion... imports.
69
from lp.registry.errors import (
70
    CannotTransitionToCountryMirror,
11637.3.13 by j.c.sackett
Fixed all CountyMirrorAlreadySet imports.
71
    CountryMirrorAlreadySet,
11637.3.12 by j.c.sackett
Fixed CannotTranstion... imports.
72
    MirrorHasNoHTTPURL,
73
    MirrorNotOfficial,
74
    MirrorNotProbed,
75
    )
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
76
from lp.registry.interfaces.distributionmirror import (
77
    IDistributionMirror,
78
    IDistributionMirrorSet,
79
    IMirrorCDImageDistroSeries,
80
    IMirrorDistroArchSeries,
81
    IMirrorDistroSeriesSource,
82
    IMirrorProbeRecord,
83
    MirrorContent,
84
    MirrorFreshness,
85
    MirrorSpeed,
86
    MirrorStatus,
87
    PROBE_INTERVAL,
88
    )
89
from lp.registry.interfaces.distroseries import IDistroSeries
90
from lp.registry.interfaces.person import validate_public_person
9113.7.2 by Jonathan Lange
Change all pocketsuffix imports to import from registry
91
from lp.registry.interfaces.pocket import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
92
    PackagePublishingPocket,
93
    pocketsuffix,
94
    )
95
from lp.registry.interfaces.series import SeriesStatus
96
from lp.registry.interfaces.sourcepackage import SourcePackageFileType
8356.1.13 by Leonard Richardson
Moved in Spokenin and Country.
97
from lp.services.worlddata.model.country import Country
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
98
from lp.services.propertycache import cachedproperty
11411.6.12 by Julian Edwards
Move PackagePublishingStatus/Priority
99
from lp.soyuz.enums import (
100
    BinaryPackageFileType,
101
    PackagePublishingStatus,
102
    )
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
103
from lp.soyuz.interfaces.distroarchseries import IDistroArchSeries
8294.6.9 by Julian Edwards
migrate files modules to lp.soyuz
104
from lp.soyuz.model.files import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
105
    BinaryPackageFile,
106
    SourcePackageReleaseFile,
107
    )
8294.6.1 by Julian Edwards
First stab at code-reorg. Still got a discrepancy on stuff I assigned to registry but not migrated yet.
108
from lp.soyuz.model.publishing import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
109
    BinaryPackagePublishingHistory,
7659.7.1 by Julian Edwards
Remove secure publishing records.
110
    SourcePackagePublishingHistory,
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
111
    )
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
112
113
114
class DistributionMirror(SQLBase):
115
    """See IDistributionMirror"""
116
117
    implements(IDistributionMirror)
118
    _table = 'DistributionMirror'
3691.51.29 by Guilherme Salgado
Use the name in the default sort order of DistributionMirrors and fix order in tests accordingly. (hopefully for the last time)
119
    _defaultOrder = ('-speed', 'name', 'id')
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
120
121
    owner = ForeignKey(
5485.1.13 by Edwin Grubbs
Sorta working
122
        dbName='owner', foreignKey='Person',
5821.2.40 by James Henstridge
* Move all the uses of public_person_validator over to the Storm
123
        storm_validator=validate_public_person, notNull=True)
5206.9.5 by Guilherme Salgado
Database/Interface code for the date_reviewed/reviewer columns and rename the +mark-official page to +review.
124
    reviewer = ForeignKey(
5485.1.13 by Edwin Grubbs
Sorta working
125
        dbName='reviewer', foreignKey='Person',
5821.2.40 by James Henstridge
* Move all the uses of public_person_validator over to the Storm
126
        storm_validator=validate_public_person, default=None)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
127
    distribution = ForeignKey(
128
        dbName='distribution', foreignKey='Distribution', notNull=True)
129
    name = StringCol(
130
        alternateID=True, notNull=True)
131
    displayname = StringCol(
132
        notNull=False, default=None)
133
    description = StringCol(
134
        notNull=False, default=None)
135
    http_base_url = StringCol(
136
        notNull=False, default=None, unique=True)
137
    ftp_base_url = StringCol(
138
        notNull=False, default=None, unique=True)
139
    rsync_base_url = StringCol(
140
        notNull=False, default=None, unique=True)
141
    enabled = BoolCol(
142
        notNull=True, default=False)
143
    speed = EnumCol(
3691.9.91 by Guilherme Salgado
Move distributionmirror-related dbschemas to DBEnumeratedTypes
144
        notNull=True, enum=MirrorSpeed)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
145
    country = ForeignKey(
146
        dbName='country', foreignKey='Country', notNull=True)
147
    content = EnumCol(
3691.9.91 by Guilherme Salgado
Move distributionmirror-related dbschemas to DBEnumeratedTypes
148
        notNull=True, enum=MirrorContent)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
149
    official_candidate = BoolCol(
150
        notNull=True, default=False)
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
151
    status = EnumCol(
152
        notNull=True, default=MirrorStatus.PENDING_REVIEW, enum=MirrorStatus)
3859.1.10 by Guilherme Salgado
Remove an assert as discussed with James
153
    date_created = UtcDateTimeCol(notNull=True, default=UTC_NOW)
5206.9.5 by Guilherme Salgado
Database/Interface code for the date_reviewed/reviewer columns and rename the +mark-official page to +review.
154
    date_reviewed = UtcDateTimeCol(default=None)
4268.2.2 by Guilherme Salgado
Make it possible to change a mirror's whiteboard when marking it as official
155
    whiteboard = StringCol(
156
        notNull=False, default=None)
7675.612.1 by Jonathan Davies
Added country_dns_mirror to our models.
157
    country_dns_mirror = BoolCol(
158
        notNull=True, default=False)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
159
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
160
    @property
3691.51.37 by Guilherme Salgado
Some fixes and tests requested by kiko
161
    def base_url(self):
162
        """See IDistributionMirror"""
163
        if self.http_base_url is not None:
164
            return self.http_base_url
165
        else:
166
            return self.ftp_base_url
167
168
    @property
2908.4.19 by Guilherme Salgado
Fixed last issues, improved tests and make it possible for mirror owners to download the log file.
169
    def last_probe_record(self):
170
        """See IDistributionMirror"""
171
        return MirrorProbeRecord.selectFirst(
172
            MirrorProbeRecord.q.distribution_mirrorID==self.id,
173
            orderBy='-date_created')
174
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
175
    @property
3691.51.35 by Guilherme Salgado
Create a new +prober-logs page for distribution mirrors, to show all prober logs
176
    def all_probe_records(self):
177
        """See IDistributionMirror"""
3691.51.37 by Guilherme Salgado
Some fixes and tests requested by kiko
178
        return MirrorProbeRecord.selectBy(
179
            distribution_mirror=self, orderBy='-date_created')
3691.51.35 by Guilherme Salgado
Create a new +prober-logs page for distribution mirrors, to show all prober logs
180
181
    @property
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
182
    def title(self):
183
        """See IDistributionMirror"""
184
        if self.displayname:
185
            return self.displayname
186
        else:
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
187
            return self.name.capitalize()
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
188
3691.51.24 by Guilherme Salgado
Properly fix [WWW] bug 57507 and make sure release mirrors are disabled if they miss any of the files they should contain.
189
    @property
190
    def has_ftp_or_rsync_base_url(self):
191
        """See IDistributionMirror"""
5206.9.7 by Guilherme Salgado
Some changes suggested by Brad
192
        return (self.ftp_base_url is not None
193
                or self.rsync_base_url is not None)
3691.51.24 by Guilherme Salgado
Properly fix [WWW] bug 57507 and make sure release mirrors are disabled if they miss any of the files they should contain.
194
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
195
    @cachedproperty
12208.2.9 by j.c.sackett
Precache works. Finally.
196
    def arch_mirror_freshness(self):
12208.2.13 by j.c.sackett
Added tests for new properties.
197
        """See IDistributionMirror"""
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
198
        store = Store.of(self)
12208.2.9 by j.c.sackett
Precache works. Finally.
199
        mirror = store.find(
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
200
            MirrorDistroArchSeries,
201
            And(
202
                MirrorDistroArchSeries.distribution_mirror == self,
203
                MirrorDistroArchSeries.freshness != MirrorFreshness.UNKNOWN)
12208.2.7 by j.c.sackett
Lint fixes.
204
                ).order_by(Desc(MirrorDistroArchSeries.freshness)).first()
12208.2.9 by j.c.sackett
Precache works. Finally.
205
        if not mirror:
206
            return None
207
        else:
208
            return mirror.freshness
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
209
210
    @cachedproperty
12208.2.9 by j.c.sackett
Precache works. Finally.
211
    def source_mirror_freshness(self):
12208.2.13 by j.c.sackett
Added tests for new properties.
212
        """See IDistributionMirror"""
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
213
        store = Store.of(self)
12208.2.9 by j.c.sackett
Precache works. Finally.
214
        mirror = store.find(
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
215
            MirrorDistroSeriesSource,
216
            And(
217
                MirrorDistroSeriesSource.distribution_mirror == self,
218
                MirrorDistroSeriesSource.freshness != MirrorFreshness.UNKNOWN)
12208.2.7 by j.c.sackett
Lint fixes.
219
                ).order_by(Desc(MirrorDistroSeriesSource.freshness)).first()
12208.2.9 by j.c.sackett
Precache works. Finally.
220
        if not mirror:
221
            return None
222
        else:
223
            return mirror.freshness
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
224
4318.2.1 by Guilherme Salgado
Fix https://launchpad.net/bugs/53442: Allow mirror admins to delete mirrors that have never been probed before
225
    def destroySelf(self):
226
        """Delete this mirror from the database.
227
228
        Only mirrors which have never been probed can be deleted.
229
        """
230
        assert self.last_probe_record is None, (
231
            "This mirror has been probed and thus can't be removed.")
232
        SQLBase.destroySelf(self)
233
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
234
    def verifyTransitionToCountryMirror(self):
7675.612.54 by Jonathan Davies
Cleanup formatting in distributionmirror.py.
235
        """Verify that a mirror can be set as a country mirror.
236
237
        Return True if valid, otherwise raise a subclass of
238
        CannotTransitionToCountryMirror.
239
        """
7675.612.72 by Jonathan Davies
Ensure that we can't set a mirror that's a country mirror as a country mirror
240
241
        current_country_mirror = self.distribution.getCountryMirror(
242
            self.country, self.content)
243
244
        if current_country_mirror is not None:
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
245
            # Country already has a country mirror.
7675.612.51 by Jonathan Davies
Start arguments on a new lines.
246
            raise CountryMirrorAlreadySet(
7675.612.54 by Jonathan Davies
Cleanup formatting in distributionmirror.py.
247
                "%s already has a country %s mirror set." % (
248
                    self.country.name, self.content))
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
249
250
        if not self.isOfficial():
251
            # Only official mirrors may be set as country mirrors.
7675.612.51 by Jonathan Davies
Start arguments on a new lines.
252
            raise MirrorNotOfficial(
253
                "This mirror may not be set as a country mirror as it is not "
254
                "an official mirror.")
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
255
256
        if self.http_base_url is None:
257
            # Country mirrors must have HTTP URLs set.
7675.612.68 by Jonathan Davies
Renamed MirrorHasNoHTTPUrl to MirrorHasNoHTTPURL.
258
            raise MirrorHasNoHTTPURL(
7675.612.51 by Jonathan Davies
Start arguments on a new lines.
259
                "This mirror may not be set as a country mirror as it does "
260
                "not have an HTTP URL set.")
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
261
262
        if not self.last_probe_record:
263
            # Only mirrors which have been probed may be set as country
264
            # mirrors.
7675.612.51 by Jonathan Davies
Start arguments on a new lines.
265
            raise MirrorNotProbed(
7675.612.54 by Jonathan Davies
Cleanup formatting in distributionmirror.py.
266
                "This mirror may not be set as a country mirror as it has "
267
                "not been probed.")
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
268
269
        # Verification done.
270
        return True
271
272
    def canTransitionToCountryMirror(self):
7675.612.70 by Jonathan Davies
Exposed canTransitionToCountryMirror() so that users can see if a mirror is
273
        """See `IDistributionMirror`."""
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
274
        try:
7675.612.54 by Jonathan Davies
Cleanup formatting in distributionmirror.py.
275
            return self.verifyTransitionToCountryMirror()
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
276
        except CannotTransitionToCountryMirror:
277
            return False
278
279
    def transitionToCountryMirror(self, country_dns_mirror):
280
        """See `IDistributionMirror`."""
7675.612.73 by Jonathan Davies
Reverted MirrorAlreadyCountryMirror; no-op like
281
282
        # country_dns_mirror has not been changed, do nothing.
283
        if self.country_dns_mirror == country_dns_mirror:
284
            return
285
7675.612.15 by Jonathan Davies
Created transitionToCountryMirror() model and helper functions.
286
        # Environment sanity checks.
287
        if country_dns_mirror:
288
            self.verifyTransitionToCountryMirror()
289
290
        self.country_dns_mirror = country_dns_mirror
291
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
292
    def getOverallFreshness(self):
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
293
        """See IDistributionMirror"""
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
294
        # XXX Guilherme Salgado 2006-08-16:
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
295
        # We shouldn't be using MirrorFreshness to represent the overall
296
        # freshness of a mirror, but for now it'll do the job and we'll use
297
        # the UNKNOWN freshness to represent a mirror without any content
298
        # (which may mean the mirror was never verified or it was verified
299
        # and no content was found).
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
300
        if self.content == MirrorContent.RELEASE:
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
301
            if self.cdimage_series:
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
302
                return MirrorFreshness.UP
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
303
            else:
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
304
                return MirrorFreshness.UNKNOWN
12208.2.5 by j.c.sackett
Updated the getOverallFreshness method to use cachedproperties that are prepopulated when archive mirrors are queried for.
305
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
306
        elif self.content == MirrorContent.ARCHIVE:
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
307
            # Return the worst (i.e. highest valued) mirror freshness out of
308
            # all mirrors (binary and source) for this distribution mirror.
12208.2.9 by j.c.sackett
Precache works. Finally.
309
            arch_mirror_freshness = self.arch_mirror_freshness
310
            source_mirror_freshness = self.source_mirror_freshness
12561.1.7 by Curtis Hovey
Hush lint.
311
12208.2.14 by j.c.sackett
Cleaned up conditionals per review in getOverallFreshness
312
            # Return unknown if no content
12208.2.9 by j.c.sackett
Precache works. Finally.
313
            if (arch_mirror_freshness is None and
314
                source_mirror_freshness is None):
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
315
                return MirrorFreshness.UNKNOWN
12208.2.14 by j.c.sackett
Cleaned up conditionals per review in getOverallFreshness
316
12561.1.7 by Curtis Hovey
Hush lint.
317
12208.2.14 by j.c.sackett
Cleaned up conditionals per review in getOverallFreshness
318
            # Return arch_mirror freshness if we have no source mirror.
319
            if  (arch_mirror_freshness is not None and
12208.2.9 by j.c.sackett
Precache works. Finally.
320
                  source_mirror_freshness is None):
321
                return arch_mirror_freshness
12561.1.7 by Curtis Hovey
Hush lint.
322
12208.2.14 by j.c.sackett
Cleaned up conditionals per review in getOverallFreshness
323
            # Return source_mirror freshness if we have no arch mirror.
324
            if (arch_mirror_freshness is None and
325
                source_mirror_freshness is not None):
326
                return source_mirror_freshness
327
328
            # Return the freshest data if we have data for both.
329
            if source_mirror_freshness > arch_mirror_freshness:
12208.2.9 by j.c.sackett
Precache works. Finally.
330
                return source_mirror_freshness
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
331
            else:
12208.2.14 by j.c.sackett
Cleaned up conditionals per review in getOverallFreshness
332
                return arch_mirror_freshness
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
333
        else:
334
            raise AssertionError(
335
                'DistributionMirror.content is not ARCHIVE nor RELEASE: %r'
336
                % self.content)
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
337
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
338
    def isOfficial(self):
339
        """See IDistributionMirror"""
5206.9.7 by Guilherme Salgado
Some changes suggested by Brad
340
        return (self.official_candidate
341
                and self.status == MirrorStatus.OFFICIAL)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
342
3691.51.26 by Guilherme Salgado
Lots of tests and other things that Bjorn requested
343
    def shouldDisable(self, expected_file_count=None):
344
        """See IDistributionMirror"""
345
        if self.content == MirrorContent.RELEASE:
346
            if expected_file_count is None:
347
                raise AssertionError(
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
348
                    'For series mirrors we need to know the '
3691.51.26 by Guilherme Salgado
Lots of tests and other things that Bjorn requested
349
                    'expected_file_count in order to tell if it should '
350
                    'be disabled or not.')
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
351
            if expected_file_count > self.cdimage_series.count():
3691.51.26 by Guilherme Salgado
Lots of tests and other things that Bjorn requested
352
                return True
353
        else:
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
354
            if not (self.source_series or self.arch_series):
3691.51.26 by Guilherme Salgado
Lots of tests and other things that Bjorn requested
355
                return True
356
        return False
357
5447.3.1 by Guilherme Salgado
Fix the bug
358
    def disable(self, notify_owner, log):
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
359
        """See IDistributionMirror"""
3691.51.50 by Guilherme Salgado
Send notifications about mirror being disabled only if a mirror has never been probed or if it was previously enabled.
360
        assert self.last_probe_record is not None, (
361
            "This method can't be called on a mirror that has never been "
362
            "probed.")
3691.214.22 by Guilherme Salgado
Add an option to the mirror-prober script to not send notification to mirror owners.
363
        if self.enabled or self.all_probe_records.count() == 1:
5447.3.1 by Guilherme Salgado
Fix the bug
364
            self._sendFailureNotification(notify_owner, log)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
365
        self.enabled = False
3691.214.22 by Guilherme Salgado
Add an option to the mirror-prober script to not send notification to mirror owners.
366
5447.3.1 by Guilherme Salgado
Fix the bug
367
    def _sendFailureNotification(self, notify_owner, log):
3691.214.22 by Guilherme Salgado
Add an option to the mirror-prober script to not send notification to mirror owners.
368
        """Send a failure notification to the distribution's mirror admins and
369
        to the mirror owner, in case notify_owner is True.
370
        """
12561.1.3 by Curtis Hovey
Moved registry email templates to lp.registry.
371
        template = get_email_template(
372
            'notify-mirror-owner.txt', app='registry')
3691.214.22 by Guilherme Salgado
Add an option to the mirror-prober script to not send notification to mirror owners.
373
        fromaddress = format_address(
6041.1.1 by Curtis Hovey
Migrated the canonical section.
374
            "Launchpad Mirror Prober", config.canonical.noreply_from_address)
3691.214.22 by Guilherme Salgado
Add an option to the mirror-prober script to not send notification to mirror owners.
375
376
        replacements = {
377
            'distro': self.distribution.title,
378
            'mirror_name': self.name,
379
            'mirror_url': canonical_url(self),
5447.3.1 by Guilherme Salgado
Fix the bug
380
            'log_snippet': "\n".join(log.split('\n')[:20]),
3691.214.22 by Guilherme Salgado
Add an option to the mirror-prober script to not send notification to mirror owners.
381
            'logfile_url': self.last_probe_record.log_file.http_url}
382
        message = template % replacements
383
        subject = "Launchpad: Verification of %s failed" % self.name
384
7495.2.3 by Curtis Hovey
Renamed contactEmailAddresses => get_contact_email_addresses. Fixed long lines.
385
        mirror_admin_address = get_contact_email_addresses(
3691.214.22 by Guilherme Salgado
Add an option to the mirror-prober script to not send notification to mirror owners.
386
            self.distribution.mirror_admin)
5447.3.1 by Guilherme Salgado
Fix the bug
387
        simple_sendmail(fromaddress, mirror_admin_address, subject, message)
3691.214.22 by Guilherme Salgado
Add an option to the mirror-prober script to not send notification to mirror owners.
388
389
        if notify_owner:
7495.2.3 by Curtis Hovey
Renamed contactEmailAddresses => get_contact_email_addresses. Fixed long lines.
390
            owner_address = get_contact_email_addresses(self.owner)
12400.1.2 by William Grant
Notifying a mirror's owner of a probe failure will no longer crash if the owner is deactivated.
391
            if len(owner_address) > 0:
392
                simple_sendmail(fromaddress, owner_address, subject, message)
3691.51.50 by Guilherme Salgado
Send notifications about mirror being disabled only if a mirror has never been probed or if it was previously enabled.
393
2908.4.12 by Guilherme Salgado
Lots of fixes Andrew suggested, fixed DB patch from Stuart and some tests to the mirror prober.
394
    def newProbeRecord(self, log_file):
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
395
        """See IDistributionMirror"""
2908.4.12 by Guilherme Salgado
Lots of fixes Andrew suggested, fixed DB patch from Stuart and some tests to the mirror prober.
396
        return MirrorProbeRecord(distribution_mirror=self, log_file=log_file)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
397
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
398
    def deleteMirrorDistroArchSeries(self, distro_arch_series, pocket,
4318.2.1 by Guilherme Salgado
Fix https://launchpad.net/bugs/53442: Allow mirror admins to delete mirrors that have never been probed before
399
                                     component):
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
400
        """See IDistributionMirror"""
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
401
        mirror = MirrorDistroArchSeries.selectOneBy(
402
            distribution_mirror=self, distro_arch_series=distro_arch_series,
3691.62.21 by kiko
Clean up the use of ID/.id in select*By and constructors
403
            pocket=pocket, component=component)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
404
        if mirror is not None:
405
            mirror.destroySelf()
406
11637.3.20 by j.c.sackett
Lint fixes.
407
    def _getMirrorDistroArchSeries(
408
        self, distro_arch_series, pocket, component):
10739.1.12 by Jonathan Davies
Wrapped first line comments of functions to one line.
409
        """Return MirrorDistroArchSeries given a arch series and pocket."""
10739.1.8 by Jonathan Davies
Readded comments for _getMirrorDistroArchSeries and
410
10739.1.11 by Jonathan Davies
Use IStore instead of SQLBase for MirrorDistroArchSeries and
411
        return IStore(MirrorDistroArchSeries).find(
412
            MirrorDistroArchSeries,
3691.62.21 by kiko
Clean up the use of ID/.id in select*By and constructors
413
            distribution_mirror=self,
10739.1.11 by Jonathan Davies
Use IStore instead of SQLBase for MirrorDistroArchSeries and
414
            distro_arch_series=distro_arch_series,
415
            pocket=pocket,
416
            component=component).one()
10739.1.1 by Jonathan Davies
Made the prober skip stuff which are obsolete and ones which were not on the
417
418
    def ensureMirrorDistroArchSeries(self, distro_arch_series, pocket,
419
                                     component):
420
        """See `IDistributionMirror`."""
421
        assert IDistroArchSeries.providedBy(distro_arch_series)
10739.1.7 by Jonathan Davies
Made getMirrorDistroArchSeries and getMirrorDistroSeriesSource private.
422
        mirror = self._getMirrorDistroArchSeries(
10739.1.1 by Jonathan Davies
Made the prober skip stuff which are obsolete and ones which were not on the
423
                distro_arch_series=distro_arch_series,
424
                pocket=pocket, component=component)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
425
        if mirror is None:
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
426
            mirror = MirrorDistroArchSeries(
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
427
                pocket=pocket, distribution_mirror=self,
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
428
                distro_arch_series=distro_arch_series,
3691.62.21 by kiko
Clean up the use of ID/.id in select*By and constructors
429
                component=component)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
430
        return mirror
431
10739.1.7 by Jonathan Davies
Made getMirrorDistroArchSeries and getMirrorDistroSeriesSource private.
432
    def _getMirrorDistroSeriesSource(self, distroseries, pocket, component):
10739.1.12 by Jonathan Davies
Wrapped first line comments of functions to one line.
433
        """Return MirrorDistroSeriesSource given a arch series and pocket."""
10739.1.8 by Jonathan Davies
Readded comments for _getMirrorDistroArchSeries and
434
10739.1.11 by Jonathan Davies
Use IStore instead of SQLBase for MirrorDistroArchSeries and
435
        return IStore(MirrorDistroSeriesSource).find(
436
            MirrorDistroSeriesSource,
437
            distribution_mirror=self,
438
            distroseries=distroseries,
439
            pocket=pocket,
440
            component=component).one()
10739.1.1 by Jonathan Davies
Made the prober skip stuff which are obsolete and ones which were not on the
441
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
442
    def ensureMirrorDistroSeriesSource(self, distroseries, pocket, component):
10739.1.1 by Jonathan Davies
Made the prober skip stuff which are obsolete and ones which were not on the
443
        """See `IDistributionMirror`."""
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
444
        assert IDistroSeries.providedBy(distroseries)
10739.1.7 by Jonathan Davies
Made getMirrorDistroArchSeries and getMirrorDistroSeriesSource private.
445
        mirror = self._getMirrorDistroSeriesSource(
10739.1.1 by Jonathan Davies
Made the prober skip stuff which are obsolete and ones which were not on the
446
            distroseries=distroseries, pocket=pocket, component=component)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
447
        if mirror is None:
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
448
            mirror = MirrorDistroSeriesSource(
449
                distribution_mirror=self, distroseries=distroseries,
3691.62.21 by kiko
Clean up the use of ID/.id in select*By and constructors
450
                pocket=pocket, component=component)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
451
        return mirror
452
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
453
    def deleteMirrorDistroSeriesSource(self, distroseries, pocket, component):
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
454
        """See IDistributionMirror"""
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
455
        mirror = MirrorDistroSeriesSource.selectOneBy(
456
            distribution_mirror=self, distroseries=distroseries,
3691.62.21 by kiko
Clean up the use of ID/.id in select*By and constructors
457
            pocket=pocket, component=component)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
458
        if mirror is not None:
459
            mirror.destroySelf()
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
460
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
461
    def ensureMirrorCDImageSeries(self, distroseries, flavour):
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
462
        """See IDistributionMirror"""
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
463
        mirror = MirrorCDImageDistroSeries.selectOneBy(
464
            distribution_mirror=self, distroseries=distroseries,
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
465
            flavour=flavour)
466
        if mirror is None:
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
467
            mirror = MirrorCDImageDistroSeries(
468
                distribution_mirror=self, distroseries=distroseries,
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
469
                flavour=flavour)
470
        return mirror
471
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
472
    def deleteMirrorCDImageSeries(self, distroseries, flavour):
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
473
        """See IDistributionMirror"""
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
474
        mirror = MirrorCDImageDistroSeries.selectOneBy(
475
            distribution_mirror=self, distroseries=distroseries,
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
476
            flavour=flavour)
477
        if mirror is not None:
478
            mirror.destroySelf()
479
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
480
    def deleteAllMirrorCDImageSeries(self):
3691.214.1 by Guilherme Salgado
Fix https://launchpad.net/bugs/46662 (Mirror prober should clean all MirrorCDImageDistroRelease rows for a given mirror before probing)
481
        """See IDistributionMirror"""
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
482
        for mirror in self.cdimage_series:
3691.214.1 by Guilherme Salgado
Fix https://launchpad.net/bugs/46662 (Mirror prober should clean all MirrorCDImageDistroRelease rows for a given mirror before probing)
483
            mirror.destroySelf()
484
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
485
    @property
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
486
    def arch_series(self):
5218.1.4 by Christian Robottom Reis
Factor out sources.list generation to a separate view, template and pseudo-content class. Use this view to render entries for PPAs. Then update distribution mirror pages to also use the same view.
487
        """See IDistributionMirror"""
488
        return MirrorDistroArchSeries.selectBy(distribution_mirror=self)
489
490
    @property
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
491
    def cdimage_series(self):
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
492
        """See IDistributionMirror"""
4318.2.1 by Guilherme Salgado
Fix https://launchpad.net/bugs/53442: Allow mirror admins to delete mirrors that have never been probed before
493
        return MirrorCDImageDistroSeries.selectBy(distribution_mirror=self)
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
494
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
495
    @property
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
496
    def source_series(self):
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
497
        """See IDistributionMirror"""
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
498
        return MirrorDistroSeriesSource.selectBy(distribution_mirror=self)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
499
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
500
    def getSummarizedMirroredSourceSeries(self):
3525.1.5 by Guilherme Salgado
Loads of changes to summarize the arch/source releases that a mirror contains and to display the releases/flavours that a release mirror contains.
501
        """See IDistributionMirror"""
502
        query = """
5121.2.6 by Stuart Bishop
Some required code updates
503
            MirrorDistroSeriesSource.id IN (
12561.1.7 by Curtis Hovey
Hush lint.
504
              SELECT DISTINCT ON (
505
                        MirrorDistroSeriesSource.distribution_mirror,
506
                        MirrorDistroSeriesSource.distroseries)
5121.2.6 by Stuart Bishop
Some required code updates
507
                     MirrorDistroSeriesSource.id
508
              FROM MirrorDistroSeriesSource, DistributionMirror
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
509
              WHERE DistributionMirror.id =
5121.2.6 by Stuart Bishop
Some required code updates
510
                         MirrorDistroSeriesSource.distribution_mirror
4285.2.5 by Mark Shuttleworth
Test fixes for renamed series
511
                    AND DistributionMirror.id = %(mirrorid)s
512
                    AND DistributionMirror.distribution = %(distribution)s
5121.2.6 by Stuart Bishop
Some required code updates
513
              ORDER BY MirrorDistroSeriesSource.distribution_mirror,
514
                       MirrorDistroSeriesSource.distroseries,
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
515
                       MirrorDistroSeriesSource.freshness DESC)
3525.1.8 by Guilherme Salgado
Lots of cleanups and improvements suggested by kiko/spiv
516
            """ % sqlvalues(distribution=self.distribution, mirrorid=self)
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
517
        return MirrorDistroSeriesSource.select(query)
3525.1.5 by Guilherme Salgado
Loads of changes to summarize the arch/source releases that a mirror contains and to display the releases/flavours that a release mirror contains.
518
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
519
    def getSummarizedMirroredArchSeries(self):
3525.1.5 by Guilherme Salgado
Loads of changes to summarize the arch/source releases that a mirror contains and to display the releases/flavours that a release mirror contains.
520
        """See IDistributionMirror"""
521
        query = """
5121.2.6 by Stuart Bishop
Some required code updates
522
            MirrorDistroArchSeries.id IN (
12561.1.7 by Curtis Hovey
Hush lint.
523
                SELECT DISTINCT ON (
524
                        MirrorDistroArchSeries.distribution_mirror,
525
                        MirrorDistroArchSeries.distroarchseries)
5121.2.6 by Stuart Bishop
Some required code updates
526
                       MirrorDistroArchSeries.id
527
                FROM MirrorDistroArchSeries, DistributionMirror
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
528
                WHERE DistributionMirror.id =
5121.2.6 by Stuart Bishop
Some required code updates
529
                            MirrorDistroArchSeries.distribution_mirror
3525.1.8 by Guilherme Salgado
Lots of cleanups and improvements suggested by kiko/spiv
530
                      AND DistributionMirror.id = %(mirrorid)s
531
                      AND DistributionMirror.distribution = %(distribution)s
5121.2.6 by Stuart Bishop
Some required code updates
532
                ORDER BY MirrorDistroArchSeries.distribution_mirror,
533
                         MirrorDistroArchSeries.distroarchseries,
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
534
                         MirrorDistroArchSeries.freshness DESC)
3525.1.8 by Guilherme Salgado
Lots of cleanups and improvements suggested by kiko/spiv
535
            """ % sqlvalues(distribution=self.distribution, mirrorid=self)
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
536
        return MirrorDistroArchSeries.select(query)
3525.1.5 by Guilherme Salgado
Loads of changes to summarize the arch/source releases that a mirror contains and to display the releases/flavours that a release mirror contains.
537
3525.1.8 by Guilherme Salgado
Lots of cleanups and improvements suggested by kiko/spiv
538
    def getExpectedPackagesPaths(self):
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
539
        """See IDistributionMirror"""
540
        paths = []
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
541
        for series in self.distribution.series:
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
542
            for pocket, suffix in pocketsuffix.items():
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
543
                for component in series.components:
544
                    for arch_series in series.architectures:
10739.1.4 by Jonathan Davies
Don't probe if the series is obsolete and the architecture is unofficial.
545
                        # Skip unsupported series and unofficial architectures
546
                        # for official series and ones which were not on the
547
                        # mirror on its last probe.
548
                        if ((series.status == SeriesStatus.OBSOLETE or
549
                                not arch_series.official) and
10739.1.9 by Jonathan Davies
Refactor function arguments.
550
                                not self._getMirrorDistroArchSeries(
551
                                    arch_series, pocket, component)):
3691.9.5 by Guilherme Salgado
Cheap attempt to try and avoid https://launchpad.net/bugs/54791 from biting us
552
                            continue
553
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
554
                        path = ('dists/%s%s/%s/binary-%s/Packages.gz'
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
555
                                % (series.name, suffix, component.name,
556
                                   arch_series.architecturetag))
557
                        paths.append((arch_series, pocket, component, path))
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
558
        return paths
559
3525.1.8 by Guilherme Salgado
Lots of cleanups and improvements suggested by kiko/spiv
560
    def getExpectedSourcesPaths(self):
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
561
        """See IDistributionMirror"""
562
        paths = []
9760.8.1 by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase.
563
        for series in self.distribution.series:
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
564
            for pocket, suffix in pocketsuffix.items():
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
565
                for component in series.components:
10739.1.1 by Jonathan Davies
Made the prober skip stuff which are obsolete and ones which were not on the
566
                    # Skip sources for series which are obsolete and ones
567
                    # which were not on the mirror on its last probe.
568
                    if (series.status == SeriesStatus.OBSOLETE and
10739.1.9 by Jonathan Davies
Refactor function arguments.
569
                        not self._getMirrorDistroSeriesSource(
570
                            series, pocket, component)):
10739.1.1 by Jonathan Davies
Made the prober skip stuff which are obsolete and ones which were not on the
571
                        continue
10739.1.5 by Jonathan Davies
Corrected function name.
572
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
573
                    path = ('dists/%s%s/%s/source/Sources.gz'
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
574
                            % (series.name, suffix, component.name))
575
                    paths.append((series, pocket, component, path))
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
576
        return paths
577
578
579
class DistributionMirrorSet:
580
    """See IDistributionMirrorSet"""
581
11637.3.20 by j.c.sackett
Lint fixes.
582
    implements(IDistributionMirrorSet)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
583
584
    def __getitem__(self, mirror_id):
585
        """See IDistributionMirrorSet"""
586
        return DistributionMirror.get(mirror_id)
587
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
588
    def getBestMirrorsForCountry(self, country, mirror_type):
3691.214.23 by Guilherme Salgado
New API for looking up the best mirrors to be used in a given country
589
        """See IDistributionMirrorSet"""
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
590
        # As per mvo's request we only return mirrors which have an
591
        # http_base_url.
3691.214.24 by Guilherme Salgado
Implement the new +countrymirrors-archive page, together with some fixes to its underlying bits, new/improved tests and a new argument to the prober script, which causes it to not connect to anything other than localhost
592
        country_id = None
593
        if country is not None:
594
            country_id = country.id
595
        base_query = AND(
5821.2.60 by James Henstridge
Don't use sqlvalues() with compiled expressions.
596
            DistributionMirror.q.content == mirror_type,
3691.214.23 by Guilherme Salgado
New API for looking up the best mirrors to be used in a given country
597
            DistributionMirror.q.enabled == True,
598
            DistributionMirror.q.http_base_url != None,
599
            DistributionMirror.q.official_candidate == True,
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
600
            DistributionMirror.q.status == MirrorStatus.OFFICIAL)
3691.214.24 by Guilherme Salgado
Implement the new +countrymirrors-archive page, together with some fixes to its underlying bits, new/improved tests and a new argument to the prober script, which causes it to not connect to anything other than localhost
601
        query = AND(DistributionMirror.q.countryID == country_id, base_query)
5447.2.1 by Guilherme Salgado
Fix bug 161088 by randomizing the results of getBestMirrorsForCountry().
602
        # The list of mirrors returned by this method is fed to apt through
603
        # launchpad.net, so we order the results randomly in a lame attempt to
604
        # balance the load on the mirrors.
5821.2.6 by James Henstridge
Port forward storm integration work. This is enough for the Launchpad
605
        order_by = [Func('random')]
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
606
        mirrors = shortlist(
5447.2.1 by Guilherme Salgado
Fix bug 161088 by randomizing the results of getBestMirrorsForCountry().
607
            DistributionMirror.select(query, orderBy=order_by),
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
608
            longest_expected=50)
3691.214.24 by Guilherme Salgado
Implement the new +countrymirrors-archive page, together with some fixes to its underlying bits, new/improved tests and a new argument to the prober script, which causes it to not connect to anything other than localhost
609
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
610
        if not mirrors and country is not None:
3691.214.24 by Guilherme Salgado
Implement the new +countrymirrors-archive page, together with some fixes to its underlying bits, new/improved tests and a new argument to the prober script, which causes it to not connect to anything other than localhost
611
            continent = country.continent
612
            query = AND(
613
                Country.q.continentID == continent.id,
614
                DistributionMirror.q.countryID == Country.q.id,
615
                base_query)
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
616
            mirrors.extend(shortlist(
5447.2.1 by Guilherme Salgado
Fix bug 161088 by randomizing the results of getBestMirrorsForCountry().
617
                DistributionMirror.select(query, orderBy=order_by),
10568.3.2 by Curtis Hovey
Increased the getBestMirrorsForCountry shortlist to 300.
618
                longest_expected=300))
3691.214.24 by Guilherme Salgado
Implement the new +countrymirrors-archive page, together with some fixes to its underlying bits, new/improved tests and a new argument to the prober script, which causes it to not connect to anything other than localhost
619
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
620
        if mirror_type == MirrorContent.ARCHIVE:
621
            main_mirror = getUtility(
622
                ILaunchpadCelebrities).ubuntu_archive_mirror
623
        elif mirror_type == MirrorContent.RELEASE:
624
            main_mirror = getUtility(
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
625
                ILaunchpadCelebrities).ubuntu_cdimage_mirror
3691.214.27 by Guilherme Salgado
A bunch of changes requested by Bjorn
626
        else:
627
            raise AssertionError("Unknown mirror type: %s" % mirror_type)
628
        assert main_mirror is not None, 'Main mirror was not found'
629
        if main_mirror not in mirrors:
630
            mirrors.append(main_mirror)
3691.214.23 by Guilherme Salgado
New API for looking up the best mirrors to be used in a given country
631
        return mirrors
632
4687.1.1 by Guilherme Salgado
Implement a limit to the number of mirrors we probe. (Fix https://bugs.launchpad.net/launchpad/+bug/123954)
633
    def getMirrorsToProbe(
634
            self, content_type, ignore_last_probe=False, limit=None):
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
635
        """See IDistributionMirrorSet"""
636
        query = """
4687.1.1 by Guilherme Salgado
Implement a limit to the number of mirrors we probe. (Fix https://bugs.launchpad.net/launchpad/+bug/123954)
637
            SELECT distributionmirror.id, MAX(mirrorproberecord.date_created)
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
638
            FROM distributionmirror
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
639
            LEFT OUTER JOIN mirrorproberecord
12561.1.7 by Curtis Hovey
Hush lint.
640
                ON mirrorproberecord.distribution_mirror =
641
                    distributionmirror.id
3691.51.32 by Guilherme Salgado
Fix the prober to always check ALL official mirrors (disabled or not), but keep the disabled ones out of public mirror listings
642
            WHERE distributionmirror.content = %s
3525.1.5 by Guilherme Salgado
Loads of changes to summarize the arch/source releases that a mirror contains and to display the releases/flavours that a release mirror contains.
643
                AND distributionmirror.official_candidate IS TRUE
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
644
                AND distributionmirror.status = %s
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
645
            GROUP BY distributionmirror.id
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
646
            """ % sqlvalues(content_type, MirrorStatus.OFFICIAL)
3525.1.8 by Guilherme Salgado
Lots of cleanups and improvements suggested by kiko/spiv
647
648
        if not ignore_last_probe:
649
            query += """
4687.1.1 by Guilherme Salgado
Implement a limit to the number of mirrors we probe. (Fix https://bugs.launchpad.net/launchpad/+bug/123954)
650
                HAVING MAX(mirrorproberecord.date_created) IS NULL
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
651
                    OR MAX(mirrorproberecord.date_created)
3525.1.8 by Guilherme Salgado
Lots of cleanups and improvements suggested by kiko/spiv
652
                        < %s - '%s hours'::interval
653
                """ % sqlvalues(UTC_NOW, PROBE_INTERVAL)
654
4687.1.1 by Guilherme Salgado
Implement a limit to the number of mirrors we probe. (Fix https://bugs.launchpad.net/launchpad/+bug/123954)
655
        query += """
656
            ORDER BY MAX(COALESCE(
657
                mirrorproberecord.date_created, '1970-01-01')) ASC, id"""
658
659
        if limit is not None:
660
            query += " LIMIT %d" % limit
661
6555.7.9 by Stuart Bishop
Use new store selection api
662
        store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
5206.9.7 by Guilherme Salgado
Some changes suggested by Brad
663
        ids = ", ".join(str(id)
5821.2.76 by James Henstridge
Get rid of a use of SQLBase._connection in the DistributionMirror code.
664
                        for (id, date_created) in store.execute(query))
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
665
        query = '1 = 2'
666
        if ids:
667
            query = 'id IN (%s)' % ids
668
        return DistributionMirror.select(query)
669
3564.3.2 by Diogo Matsubara
add getBy* methods to IDistributionMirrorSet
670
    def getByName(self, name):
671
        """See IDistributionMirrorSet"""
3564.3.7 by Diogo Matsubara
review comments
672
        return DistributionMirror.selectOneBy(name=name)
3564.3.2 by Diogo Matsubara
add getBy* methods to IDistributionMirrorSet
673
674
    def getByHttpUrl(self, url):
675
        """See IDistributionMirrorSet"""
3564.3.7 by Diogo Matsubara
review comments
676
        return DistributionMirror.selectOneBy(http_base_url=url)
3564.3.2 by Diogo Matsubara
add getBy* methods to IDistributionMirrorSet
677
678
    def getByFtpUrl(self, url):
679
        """See IDistributionMirrorSet"""
3564.3.7 by Diogo Matsubara
review comments
680
        return DistributionMirror.selectOneBy(ftp_base_url=url)
3564.3.2 by Diogo Matsubara
add getBy* methods to IDistributionMirrorSet
681
682
    def getByRsyncUrl(self, url):
683
        """See IDistributionMirrorSet"""
3564.3.7 by Diogo Matsubara
review comments
684
        return DistributionMirror.selectOneBy(rsync_base_url=url)
3564.3.2 by Diogo Matsubara
add getBy* methods to IDistributionMirrorSet
685
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
686
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
687
class _MirrorSeriesMixIn:
688
    """A class containing some commonalities between MirrorDistroArchSeries
689
    and MirrorDistroSeriesSource.
2908.4.21 by Guilherme Salgado
Add an email template and a docstring I had forgotten
690
691
    This class is not meant to be used alone. Instead, both
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
692
    MirrorDistroSeriesSource and MirrorDistroArchSeries should inherit from
2908.4.21 by Guilherme Salgado
Add an email template and a docstring I had forgotten
693
    it and override the methods and attributes that say so.
694
    """
695
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
696
    # The freshness_times map defines levels for specifying how up to date a
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
697
    # mirror is; we use published files to assess whether a certain level is
698
    # fulfilled by a mirror. The map is used in combination with a special
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
699
    # freshness UP that maps to the latest published file for that
700
    # distribution series, component and pocket: if that file is found, we
701
    # consider the distribution to be up to date; if it is not found we then
702
    # look through the rest of the map to try and determine at what level
703
    # the mirror is.
704
    freshness_times = [
705
        (MirrorFreshness.ONEHOURBEHIND, 1.5),
706
        (MirrorFreshness.TWOHOURSBEHIND, 2.5),
707
        (MirrorFreshness.SIXHOURSBEHIND, 6.5),
708
        (MirrorFreshness.ONEDAYBEHIND, 24.5),
709
        (MirrorFreshness.TWODAYSBEHIND, 48.5),
11637.3.20 by j.c.sackett
Lint fixes.
710
        (MirrorFreshness.ONEWEEKBEHIND, 168.5),
2908.4.21 by Guilherme Salgado
Add an email template and a docstring I had forgotten
711
        ]
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
712
713
    def _getPackageReleaseURLFromPublishingRecord(self, publishing_record):
5206.9.7 by Guilherme Salgado
Some changes suggested by Brad
714
        """Given a publishing record, return a dictionary mapping
715
        MirrorFreshness items to URLs of files on this mirror.
2908.4.19 by Guilherme Salgado
Fixed last issues, improved tests and make it possible for mirror owners to download the log file.
716
717
        Must be overwritten on subclasses.
718
        """
719
        raise NotImplementedError
720
3691.51.37 by Guilherme Salgado
Some fixes and tests requested by kiko
721
    def getLatestPublishingEntry(self, time_interval):
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
722
        """Return the publishing entry with the most recent datepublished.
723
724
        Time interval must be a tuple of the form (start, end), and only
725
        records whose datepublished is between start and end are considered.
726
        """
727
        raise NotImplementedError
728
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
729
    def getURLsToCheckUpdateness(self, when=None):
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
730
        """See IMirrorDistroSeriesSource or IMirrorDistroArchSeries."""
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
731
        if when is None:
732
            when = datetime.now(pytz.timezone('UTC'))
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
733
734
        start = datetime(MINYEAR, 1, 1, tzinfo=pytz.timezone('UTC'))
735
        time_interval = (start, when)
736
        latest_upload = self.getLatestPublishingEntry(time_interval)
737
        if latest_upload is None:
738
            return {}
739
740
        url = self._getPackageReleaseURLFromPublishingRecord(latest_upload)
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
741
        urls = {MirrorFreshness.UP: url}
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
742
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
743
        # For each freshness in self.freshness_times, do:
744
        #   1) if latest_upload was published before the start of this
745
        #      freshness' time interval, skip it and move to the next item.
746
        #   2) if latest_upload was published between this freshness' time
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
747
        #      interval, adjust the end of the time interval to be identical
748
        #      to latest_upload.datepublished. We do this because even if the
749
        #      mirror doesn't have the latest upload, we can't skip that whole
750
        #      time interval: the mirror might have other packages published
751
        #      in that interval.
752
        #      This happens in pathological cases where two publications were
753
        #      done successively after a long period of time with no
754
        #      publication: if the mirror lacks the latest published package,
755
        #      we still need to check the corresponding interval or we will
756
        #      misreport the mirror as being very out of date.
757
        #   3) search for publishing records whose datepublished is between
758
        #      the specified time interval, and if one is found, append an
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
759
        #      item to the urls dictionary containing this freshness and the
760
        #      url on this mirror from where the file correspondent to that
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
761
        #      publishing record can be downloaded.
762
        last_threshold = 0
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
763
        for freshness, threshold in self.freshness_times:
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
764
            start = when - timedelta(hours=threshold)
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
765
            end = when - timedelta(hours=last_threshold)
766
            last_threshold = threshold
767
            if latest_upload.datepublished < start:
768
                continue
769
            if latest_upload.datepublished < end:
770
                end = latest_upload.datepublished
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
771
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
772
            time_interval = (start, end)
773
            upload = self.getLatestPublishingEntry(time_interval)
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
774
775
            if upload is None:
776
                # No uploads that would allow us to know the mirror was in
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
777
                # this freshness, so we better skip it.
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
778
                continue
779
780
            url = self._getPackageReleaseURLFromPublishingRecord(upload)
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
781
            urls.update({freshness: url})
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
782
783
        return urls
784
785
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
786
class MirrorCDImageDistroSeries(SQLBase):
787
    """See IMirrorCDImageDistroSeries"""
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
788
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
789
    implements(IMirrorCDImageDistroSeries)
5121.2.6 by Stuart Bishop
Some required code updates
790
    _table = 'MirrorCDImageDistroSeries'
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
791
    _defaultOrder = 'id'
792
793
    distribution_mirror = ForeignKey(
794
        dbName='distribution_mirror', foreignKey='DistributionMirror',
795
        notNull=True)
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
796
    distroseries = ForeignKey(
5121.2.6 by Stuart Bishop
Some required code updates
797
        dbName='distroseries', foreignKey='DistroSeries', notNull=True)
3525.1.1 by Guilherme Salgado
Make the mirror prober probe release mirrors, improve the UI a lot and lots of other fixes.
798
    flavour = StringCol(notNull=True)
799
800
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
801
class MirrorDistroArchSeries(SQLBase, _MirrorSeriesMixIn):
802
    """See IMirrorDistroArchSeries"""
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
803
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
804
    implements(IMirrorDistroArchSeries)
5121.2.6 by Stuart Bishop
Some required code updates
805
    _table = 'MirrorDistroArchSeries'
3525.1.5 by Guilherme Salgado
Loads of changes to summarize the arch/source releases that a mirror contains and to display the releases/flavours that a release mirror contains.
806
    _defaultOrder = [
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
807
        'distroarchseries', 'component', 'pocket', 'freshness', 'id']
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
808
809
    distribution_mirror = ForeignKey(
810
        dbName='distribution_mirror', foreignKey='DistributionMirror',
811
        notNull=True)
4285.2.5 by Mark Shuttleworth
Test fixes for renamed series
812
    distro_arch_series = ForeignKey(
5121.2.6 by Stuart Bishop
Some required code updates
813
        dbName='distroarchseries', foreignKey='DistroArchSeries',
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
814
        notNull=True)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
815
    component = ForeignKey(
816
        dbName='component', foreignKey='Component', notNull=True)
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
817
    freshness = EnumCol(
818
        notNull=True, default=MirrorFreshness.UNKNOWN, enum=MirrorFreshness)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
819
    pocket = EnumCol(
820
        notNull=True, schema=PackagePublishingPocket)
821
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
822
    def getLatestPublishingEntry(self, time_interval, deb_only=True):
7659.7.1 by Julian Edwards
Remove secure publishing records.
823
        """Return the BinaryPackagePublishingHistory record with the
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
824
        most recent datepublished.
825
826
        :deb_only: If True, return only publishing records whose
827
                   binarypackagerelease's binarypackagefile.filetype is
828
                   BinaryPackageFileType.DEB.
2908.4.19 by Guilherme Salgado
Fixed last issues, improved tests and make it possible for mirror owners to download the log file.
829
        """
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
830
        query = """
7659.7.1 by Julian Edwards
Remove secure publishing records.
831
            BinaryPackagePublishingHistory.pocket = %s
832
            AND BinaryPackagePublishingHistory.component = %s
833
            AND BinaryPackagePublishingHistory.distroarchseries = %s
834
            AND BinaryPackagePublishingHistory.archive = %s
835
            AND BinaryPackagePublishingHistory.status = %s
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
836
            """ % sqlvalues(self.pocket, self.component,
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
837
                            self.distro_arch_series,
4376.2.34 by Julian Edwards
Revert change to distributionmirror - mirrors don't have anything other than
838
                            self.distro_arch_series.main_archive,
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
839
                            PackagePublishingStatus.PUBLISHED)
840
841
        if deb_only:
842
            query += """
7659.7.1 by Julian Edwards
Remove secure publishing records.
843
                AND BinaryPackagePublishingHistory.binarypackagerelease =
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
844
                    BinaryPackageFile.binarypackagerelease
845
                AND BinaryPackageFile.filetype = %s
846
                """ % sqlvalues(BinaryPackageFileType.DEB)
847
848
        if time_interval is not None:
849
            start, end = time_interval
850
            assert end > start, '%s is not more recent than %s' % (end, start)
851
            query = (query + " AND datepublished >= %s AND datepublished < %s"
852
                     % sqlvalues(start, end))
7659.7.1 by Julian Edwards
Remove secure publishing records.
853
        return BinaryPackagePublishingHistory.selectFirst(
5206.9.7 by Guilherme Salgado
Some changes suggested by Brad
854
            query, clauseTables=['BinaryPackageFile'],
855
            orderBy='-datepublished')
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
856
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
857
    def _getPackageReleaseURLFromPublishingRecord(self, publishing_record):
12561.1.7 by Curtis Hovey
Hush lint.
858
        """Return the URL on this mirror from where the BinaryPackageRelease.
859
860
        Given a BinaryPackagePublishingHistory, return the URL on
861
        this mirror from where the BinaryPackageRelease file can be
862
        downloaded.
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
863
        """
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
864
        bpr = publishing_record.binarypackagerelease
3691.51.48 by Guilherme Salgado
Make sure ftp-only archive mirrors are probed properly
865
        base_url = self.distribution_mirror.base_url
3691.212.1 by Malcolm Cleaton
Checkpoint
866
        path = poolify(bpr.sourcepackagename, self.component.name)
2908.4.27 by Guilherme Salgado
Fix https://launchpad.net/products/launchpad/+bug/38256 (Mirror prober doesn't know how to generate the filename for binary packages whose version starts with <some-number>:)
867
        file = BinaryPackageFile.selectOneBy(
3691.62.21 by kiko
Clean up the use of ID/.id in select*By and constructors
868
            binarypackagerelease=bpr, filetype=BinaryPackageFileType.DEB)
2908.4.27 by Guilherme Salgado
Fix https://launchpad.net/products/launchpad/+bug/38256 (Mirror prober doesn't know how to generate the filename for binary packages whose version starts with <some-number>:)
869
        full_path = 'pool/%s/%s' % (path, file.libraryfile.filename)
2908.4.19 by Guilherme Salgado
Fixed last issues, improved tests and make it possible for mirror owners to download the log file.
870
        return urlappend(base_url, full_path)
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
871
872
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
873
class MirrorDistroSeriesSource(SQLBase, _MirrorSeriesMixIn):
874
    """See IMirrorDistroSeriesSource"""
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
875
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
876
    implements(IMirrorDistroSeriesSource)
5121.2.6 by Stuart Bishop
Some required code updates
877
    _table = 'MirrorDistroSeriesSource'
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
878
    _defaultOrder = ['distroseries', 'component', 'pocket', 'freshness', 'id']
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
879
880
    distribution_mirror = ForeignKey(
881
        dbName='distribution_mirror', foreignKey='DistributionMirror',
882
        notNull=True)
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
883
    distroseries = ForeignKey(
5121.2.6 by Stuart Bishop
Some required code updates
884
        dbName='distroseries', foreignKey='DistroSeries',
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
885
        notNull=True)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
886
    component = ForeignKey(
887
        dbName='component', foreignKey='Component', notNull=True)
5206.9.1 by Guilherme Salgado
Add a status column to DistributionMirror so that we can track pending-review mirrors. Also rename a few other columns and add an extra page which lists all mirrors that are pending review.
888
    freshness = EnumCol(
889
        notNull=True, default=MirrorFreshness.UNKNOWN, enum=MirrorFreshness)
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
890
    pocket = EnumCol(
891
        notNull=True, schema=PackagePublishingPocket)
892
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
893
    def getLatestPublishingEntry(self, time_interval):
894
        query = """
7659.7.1 by Julian Edwards
Remove secure publishing records.
895
            SourcePackagePublishingHistory.pocket = %s
896
            AND SourcePackagePublishingHistory.component = %s
897
            AND SourcePackagePublishingHistory.distroseries = %s
898
            AND SourcePackagePublishingHistory.archive = %s
899
            AND SourcePackagePublishingHistory.status = %s
4785.3.3 by Jeroen Vermeulen
Removed end-of-line whitespace.
900
            """ % sqlvalues(self.pocket, self.component,
4285.2.1 by Mark Shuttleworth
Massive renaming of distrorelease to distroseries
901
                            self.distroseries,
4376.2.34 by Julian Edwards
Revert change to distributionmirror - mirrors don't have anything other than
902
                            self.distroseries.main_archive,
2908.4.9 by Guilherme Salgado
Implementation of the mirror prober and a bunch other things
903
                            PackagePublishingStatus.PUBLISHED)
904
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
905
        if time_interval is not None:
906
            start, end = time_interval
907
            assert end > start
908
            query = (query + " AND datepublished >= %s AND datepublished < %s"
909
                     % sqlvalues(start, end))
7659.7.1 by Julian Edwards
Remove secure publishing records.
910
        return SourcePackagePublishingHistory.selectFirst(
3424.1.17 by Guilherme Salgado
Fix the mirror prober to always use the latest publishing record to check if a mirror is up to date.
911
            query, orderBy='-datepublished')
912
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
913
    def _getPackageReleaseURLFromPublishingRecord(self, publishing_record):
12561.1.7 by Curtis Hovey
Hush lint.
914
        """return the URL on this mirror from where the SourcePackageRelease.
915
916
        Given a SourcePackagePublishingHistory, return the URL on
917
        this mirror from where the SourcePackageRelease file can be
918
        downloaded.
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
919
        """
920
        spr = publishing_record.sourcepackagerelease
3691.51.48 by Guilherme Salgado
Make sure ftp-only archive mirrors are probed properly
921
        base_url = self.distribution_mirror.base_url
2908.4.16 by Guilherme Salgado
Change a lot of tests to use twisted's facilities and improve some of them. Also refactor lots of code and fix some things as per Andrew's review.
922
        sourcename = spr.name
3691.212.1 by Malcolm Cleaton
Checkpoint
923
        path = poolify(sourcename, self.component.name)
2908.4.27 by Guilherme Salgado
Fix https://launchpad.net/products/launchpad/+bug/38256 (Mirror prober doesn't know how to generate the filename for binary packages whose version starts with <some-number>:)
924
        file = SourcePackageReleaseFile.selectOneBy(
3691.62.21 by kiko
Clean up the use of ID/.id in select*By and constructors
925
            sourcepackagerelease=spr, filetype=SourcePackageFileType.DSC)
2908.4.27 by Guilherme Salgado
Fix https://launchpad.net/products/launchpad/+bug/38256 (Mirror prober doesn't know how to generate the filename for binary packages whose version starts with <some-number>:)
926
        full_path = 'pool/%s/%s' % (path, file.libraryfile.filename)
2908.4.19 by Guilherme Salgado
Fixed last issues, improved tests and make it possible for mirror owners to download the log file.
927
        return urlappend(base_url, full_path)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
928
929
930
class MirrorProbeRecord(SQLBase):
931
    """See IMirrorProbeRecord"""
932
933
    implements(IMirrorProbeRecord)
934
    _table = 'MirrorProbeRecord'
935
    _defaultOrder = 'id'
936
937
    distribution_mirror = ForeignKey(
938
        dbName='distribution_mirror', foreignKey='DistributionMirror',
939
        notNull=True)
940
    log_file = ForeignKey(
3691.51.12 by Guilherme Salgado
Add an overall status to distribution mirrors, improve the email notification sent when a mirror is disabled and tweak the UI a bit
941
        dbName='log_file', foreignKey='LibraryFileAlias', notNull=True)
2908.4.1 by Guilherme Salgado
First round of implementation of MirrorManagement.
942
    date_created = UtcDateTimeCol(notNull=True, default=UTC_NOW)