~launchpad-pqm/launchpad/devel

7675.1120.1 by Jeroen Vermeulen
Ditch try_and_commit; simpler this way, and no functional difference.
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
13458.1.2 by Jeroen Vermeulen
Documentation.
4
"""Publisher script class."""
5596.2.1 by Julian Edwards
Make test_publishdistro quicker. Also add --private-ppa option to publish-distro.py
5
6
__all__ = [
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
7
    'PublishDistro',
5596.2.1 by Julian Edwards
Make test_publishdistro quicker. Also add --private-ppa option to publish-distro.py
8
    ]
9
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
10
from optparse import OptionValueError
13607.3.3 by Jeroen Vermeulen
Make publishing scripts share a single lock file for a system.
11
5596.2.1 by Julian Edwards
Make test_publishdistro quicker. Also add --private-ppa option to publish-distro.py
12
from zope.component import getUtility
13
11270.1.3 by Tim Penhey
Changed NotFoundError imports - gee there were a lot of them.
14
from lp.app.errors import NotFoundError
13607.3.3 by Jeroen Vermeulen
Make publishing scripts share a single lock file for a system.
15
from lp.archivepublisher.publishing import (
16
    getPublisher,
17
    GLOBAL_PUBLISHER_LOCK,
18
    )
7675.110.3 by Curtis Hovey
Ran the migration script to move registry code to lp.registry.
19
from lp.registry.interfaces.distribution import IDistributionSet
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
20
from lp.services.scripts.base import (
21
    LaunchpadCronScript,
22
    LaunchpadScriptFailure,
23
    )
11411.6.2 by Julian Edwards
Change code imports for ArchivePurpose and ArchiveStatus
24
from lp.soyuz.enums import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
25
    ArchivePurpose,
26
    ArchiveStatus,
11411.6.2 by Julian Edwards
Change code imports for ArchivePurpose and ArchiveStatus
27
    )
28
from lp.soyuz.interfaces.archive import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
29
    IArchiveSet,
30
    MAIN_ARCHIVE_PURPOSES,
31
    )
5596.2.1 by Julian Edwards
Make test_publishdistro quicker. Also add --private-ppa option to publish-distro.py
32
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
33
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
34
def is_ppa_private(ppa):
35
    """Is `ppa` private?"""
36
    return ppa.private
37
38
39
def is_ppa_public(ppa):
40
    """Is `ppa` public?"""
41
    return not ppa.private
42
43
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
44
class PublishDistro(LaunchpadCronScript):
13458.1.2 by Jeroen Vermeulen
Documentation.
45
    """Distro publisher."""
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
46
13607.3.3 by Jeroen Vermeulen
Make publishing scripts share a single lock file for a system.
47
    lockfilename = GLOBAL_PUBLISHER_LOCK
48
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
49
    def add_my_options(self):
50
        self.parser.add_option(
51
            "-C", "--careful", action="store_true", dest="careful",
52
            default=False, help="Turns on all the below careful options.")
53
54
        self.parser.add_option(
55
            "-P", "--careful-publishing", action="store_true",
56
            dest="careful_publishing", default=False,
57
            help="Make the package publishing process careful.")
58
59
        self.parser.add_option(
60
            "-D", "--careful-domination", action="store_true",
61
            dest="careful_domination", default=False,
62
            help="Make the domination process careful.")
63
64
        self.parser.add_option(
65
            "-A", "--careful-apt", action="store_true", dest="careful_apt",
66
            default=False,
67
            help="Make index generation (e.g. apt-ftparchive) careful.")
68
69
        self.parser.add_option(
70
            "-d", "--distribution", dest="distribution", metavar="DISTRO",
13482.2.5 by Jeroen Vermeulen
Satisfy validateOptions tests.
71
            default=None, help="The distribution to publish.")
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
72
73
        self.parser.add_option(
13482.2.4 by Jeroen Vermeulen
Test new functionality. (All fail because it's not written yet, but no errors.)
74
            "-a", "--all-derived", action="store_true", dest="all_derived",
75
            default=False, help="Publish all Ubuntu-derived distributions.")
76
77
        self.parser.add_option(
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
78
            '-s', '--suite', metavar='SUITE', dest='suite', action='append',
79
            type='string', default=[], help='The suite to publish')
80
81
        self.parser.add_option(
82
            "-R", "--distsroot", dest="distsroot", metavar="SUFFIX",
83
            default=None,
84
            help=(
85
                "Override the dists path for generation of the PRIMARY and "
86
                "PARTNER archives only."))
87
88
        self.parser.add_option(
89
            "--ppa", action="store_true", dest="ppa", default=False,
90
            help="Only run over PPA archives.")
91
92
        self.parser.add_option(
93
            "--private-ppa", action="store_true", dest="private_ppa",
94
            default=False, help="Only run over private PPA archives.")
95
96
        self.parser.add_option(
97
            "--partner", action="store_true", dest="partner", default=False,
98
            help="Only run over the partner archive.")
99
100
        self.parser.add_option(
101
            "--copy-archive", action="store_true", dest="copy_archive",
102
            default=False, help="Only run over the copy archives.")
103
104
        self.parser.add_option(
105
            "--primary-debug", action="store_true", default=False,
106
            dest="primary_debug",
107
            help="Only run over the debug-symbols for primary archive.")
108
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
109
    def isCareful(self, option):
110
        """Is the given "carefulness" option enabled?
111
112
        Yes if the option is True, but also if the global "careful" option
113
        is set.
114
115
        :param option: The specific "careful" option to test, e.g.
116
            `self.options.careful_publishing`.
117
        :return: Whether the option should be treated as asking us to be
118
            careful.
119
        """
120
        return option or self.options.careful
121
13458.1.7 by Jeroen Vermeulen
Fix findSuite, and lint.
122
    def describeCare(self, option):
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
123
        """Helper: describe carefulness setting of given option.
124
125
        Produces a human-readable string saying whether the option is set
126
        to careful mode; or "overridden" to careful mode by the global
127
        "careful" option; or is left in normal mode.
128
        """
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
129
        if self.options.careful:
13458.1.7 by Jeroen Vermeulen
Fix findSuite, and lint.
130
            return "Careful (Overridden)"
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
131
        elif option:
13458.1.7 by Jeroen Vermeulen
Fix findSuite, and lint.
132
            return "Careful"
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
133
        else:
13458.1.7 by Jeroen Vermeulen
Fix findSuite, and lint.
134
            return "Normal"
135
136
    def logOption(self, name, value):
137
        """Describe the state of `option` to the debug log."""
138
        self.logger.debug("%14s: %s", name, value)
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
139
140
    def countExclusiveOptions(self):
141
        """Return the number of exclusive "mode" options that were set.
142
143
        In valid use, at most one of them should be set.
144
        """
145
        exclusive_options = [
146
            self.options.partner,
147
            self.options.ppa,
148
            self.options.private_ppa,
149
            self.options.primary_debug,
150
            self.options.copy_archive,
151
            ]
152
        return len(filter(None, exclusive_options))
153
154
    def logOptions(self):
155
        """Dump the selected options to the debug log."""
13458.1.3 by Jeroen Vermeulen
Slightly cleaner.
156
        if self.countExclusiveOptions() == 0:
157
            indexing_engine = "Apt-FTPArchive"
158
        else:
159
            indexing_engine = "Indexing"
13458.1.7 by Jeroen Vermeulen
Fix findSuite, and lint.
160
        self.logOption('Distribution', self.options.distribution)
13458.1.3 by Jeroen Vermeulen
Slightly cleaner.
161
        log_items = [
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
162
            ('Publishing', self.options.careful_publishing),
163
            ('Domination', self.options.careful_domination),
13458.1.3 by Jeroen Vermeulen
Slightly cleaner.
164
            (indexing_engine, self.options.careful_apt),
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
165
            ]
13458.1.7 by Jeroen Vermeulen
Fix findSuite, and lint.
166
        for name, option in log_items:
167
            self.logOption(name, self.describeCare(option))
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
168
169
    def validateOptions(self):
170
        """Check given options for user interface violations."""
171
        if len(self.args) > 0:
172
            raise OptionValueError(
173
                "publish-distro takes no arguments, only options.")
174
        if self.countExclusiveOptions() > 1:
175
            raise OptionValueError(
176
                "Can only specify one of partner, ppa, private-ppa, "
177
                "copy-archive and primary-debug.")
178
13482.2.6 by Jeroen Vermeulen
Hide the default distribution choice in findDistros.
179
        if self.options.all_derived and self.options.distribution is not None:
13482.2.5 by Jeroen Vermeulen
Satisfy validateOptions tests.
180
                raise OptionValueError(
181
                    "Specify --distribution or --all-derived, but not both.")
182
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
183
        for_ppa = (self.options.ppa or self.options.private_ppa)
184
        if for_ppa and self.options.distsroot:
185
            raise OptionValueError(
186
                "We should not define 'distsroot' in PPA mode!", )
187
13482.2.7 by Jeroen Vermeulen
Move finding of derived distros to IDistributionSet (and add test case for IDistributionSet).
188
    def findSelectedDistro(self):
189
        """Find the `Distribution` named by the --distribution option.
190
191
        Defaults to Ubuntu if no name was given.
192
        """
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
193
        self.logger.debug("Finding distribution object.")
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
194
        name = self.options.distribution
13482.2.7 by Jeroen Vermeulen
Move finding of derived distros to IDistributionSet (and add test case for IDistributionSet).
195
        if name is None:
196
            # Default to publishing Ubuntu.
197
            name = "ubuntu"
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
198
        distro = getUtility(IDistributionSet).getByName(name)
199
        if distro is None:
200
            raise OptionValueError("Distribution '%s' not found." % name)
13482.2.7 by Jeroen Vermeulen
Move finding of derived distros to IDistributionSet (and add test case for IDistributionSet).
201
        return distro
202
203
    def findDerivedDistros(self):
204
        """Find all Ubuntu-derived distributions."""
205
        self.logger.debug("Finding derived distributions.")
206
        return getUtility(IDistributionSet).getDerivedDistributions()
207
208
    def findDistros(self):
209
        """Find the selected distribution(s)."""
210
        if self.options.all_derived:
211
            return self.findDerivedDistros()
212
        else:
213
            return [self.findSelectedDistro()]
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
214
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
215
    def findSuite(self, distribution, suite):
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
216
        """Find the named `suite` in the selected `Distribution`.
217
13458.1.7 by Jeroen Vermeulen
Fix findSuite, and lint.
218
        :param suite: The suite name to look for.
219
        :return: A tuple of distroseries name and pocket.
220
        """
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
221
        try:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
222
            series, pocket = distribution.getDistroSeriesAndPocket(suite)
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
223
        except NotFoundError, e:
224
            raise OptionValueError(e)
13458.1.7 by Jeroen Vermeulen
Fix findSuite, and lint.
225
        return series.name, pocket
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
226
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
227
    def findAllowedSuites(self, distribution):
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
228
        """Find the selected suite(s)."""
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
229
        return set([
230
            self.findSuite(distribution, suite)
231
            for suite in self.options.suite])
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
232
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
233
    def getDebugArchive(self, distribution):
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
234
        """Find the debug archive for the selected distribution, as a list."""
8383.2.2 by Celso Providelo
Publishing DEBUG archive and its DDEBS.
235
        debug_archive = getUtility(IArchiveSet).getByDistroPurpose(
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
236
            distribution, ArchivePurpose.DEBUG)
8383.2.2 by Celso Providelo
Publishing DEBUG archive and its DDEBS.
237
        if debug_archive is None:
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
238
            raise OptionValueError(
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
239
                "Could not find DEBUG archive for %s" % distribution.name)
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
240
        return [debug_archive]
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
241
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
242
    def getCopyArchives(self, distribution):
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
243
        """Find copy archives for the selected distribution."""
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
244
        copy_archives = list(
245
            getUtility(IArchiveSet).getArchivesForDistribution(
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
246
                distribution, purposes=[ArchivePurpose.COPY]))
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
247
        if copy_archives == []:
10373.1.2 by Julian Edwards
change the script so that --copy-archive doesn't need a named archive, we will just publish any that are marked with publish=True
248
            raise LaunchpadScriptFailure("Could not find any COPY archives")
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
249
        return copy_archives
250
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
251
    def getPPAs(self, distribution):
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
252
        """Find private package archives for the selected distribution."""
253
        if self.isCareful(self.options.careful_publishing):
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
254
            return distribution.getAllPPAs()
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
255
        else:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
256
            return distribution.getPendingPublicationPPAs()
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
257
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
258
    def getTargetArchives(self, distribution):
13458.1.2 by Jeroen Vermeulen
Documentation.
259
        """Find the archive(s) selected by the script's options."""
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
260
        if self.options.partner:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
261
            return [distribution.getArchiveByComponent('partner')]
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
262
        elif self.options.ppa:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
263
            return filter(is_ppa_public, self.getPPAs(distribution))
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
264
        elif self.options.private_ppa:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
265
            return filter(is_ppa_private, self.getPPAs(distribution))
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
266
        elif self.options.primary_debug:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
267
            return self.getDebugArchive(distribution)
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
268
        elif self.options.copy_archive:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
269
            return self.getCopyArchives(distribution)
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
270
        else:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
271
            return [distribution.main_archive]
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
272
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
273
    def getPublisher(self, distribution, archive, allowed_suites):
13458.1.2 by Jeroen Vermeulen
Documentation.
274
        """Get a publisher for the given options."""
7369.2.1 by Muharem Hrnjadovic
publishdistro script revised
275
        if archive.purpose in MAIN_ARCHIVE_PURPOSES:
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
276
            description = "%s %s" % (distribution.name, archive.displayname)
7369.2.3 by Muharem Hrnjadovic
consolidated if statement
277
            # Only let the primary/partner archives override the distsroot.
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
278
            distsroot = self.options.distsroot
279
        else:
280
            description = archive.archive_url
281
            distsroot = None
282
283
        self.logger.info("Processing %s", description)
284
        return getPublisher(archive, allowed_suites, self.logger, distsroot)
285
286
    def deleteArchive(self, archive, publisher):
13458.1.2 by Jeroen Vermeulen
Documentation.
287
        """Ask `publisher` to delete `archive`."""
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
288
        if archive.purpose == ArchivePurpose.PPA:
289
            publisher.deleteArchive()
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
290
            return True
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
291
        else:
292
            # Other types of archives do not currently support deletion.
293
            self.logger.warning(
294
                "Deletion of %s skipped: operation not supported on %s",
295
                archive.displayname, archive.purpose.title)
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
296
            return False
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
297
298
    def publishArchive(self, archive, publisher):
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
299
        """Ask `publisher` to publish `archive`.
300
301
        Commits transactions along the way.
302
        """
303
        publisher.A_publish(self.isCareful(self.options.careful_publishing))
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
304
        self.txn.commit()
305
306
        # Flag dirty pockets for any outstanding deletions.
307
        publisher.A2_markPocketsWithDeletionsDirty()
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
308
        publisher.B_dominate(self.isCareful(self.options.careful_domination))
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
309
        self.txn.commit()
310
311
        # The primary and copy archives use apt-ftparchive to
312
        # generate the indexes, everything else uses the newer
313
        # internal LP code.
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
314
        careful_indexing = self.isCareful(self.options.careful_apt)
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
315
        if archive.purpose in (ArchivePurpose.PRIMARY, ArchivePurpose.COPY):
13458.1.5 by Jeroen Vermeulen
Cosmetic.
316
            publisher.C_doFTPArchive(careful_indexing)
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
317
        else:
13458.1.5 by Jeroen Vermeulen
Cosmetic.
318
            publisher.C_writeIndexes(careful_indexing)
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
319
        self.txn.commit()
320
13458.1.5 by Jeroen Vermeulen
Cosmetic.
321
        publisher.D_writeReleaseFiles(careful_indexing)
13458.1.8 by Jeroen Vermeulen
Fine-grained tests.
322
        # The caller will commit this last step.
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
323
324
    def main(self):
13458.1.2 by Jeroen Vermeulen
Documentation.
325
        """See `LaunchpadScript`."""
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
326
        self.validateOptions()
327
        self.logOptions()
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
328
329
        for distribution in self.findDistros():
330
            allowed_suites = self.findAllowedSuites(distribution)
331
            for archive in self.getTargetArchives(distribution):
13482.2.2 by Jeroen Vermeulen
Missing arg.
332
                publisher = self.getPublisher(
333
                    distribution, archive, allowed_suites)
13482.2.1 by Jeroen Vermeulen
Structural changes for multi-distro publishing, and tests.
334
335
                if archive.status == ArchiveStatus.DELETING:
336
                    work_done = self.deleteArchive(archive, publisher)
337
                elif archive.publish:
338
                    self.publishArchive(archive, publisher)
339
                    work_done = True
340
                else:
341
                    work_done = False
342
343
                if work_done:
344
                    self.txn.commit()
13458.1.1 by Jeroen Vermeulen
Convert publishdistro to a LaunchpadCronScript.
345
346
        self.logger.debug("Ciao")