~launchpad-pqm/launchpad/devel

7675.420.1 by Michael Nelson
Initial IBuildFarmJobBehavior implementation for binary packages.
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
4
# pylint: disable-msg=E0211,E0213
5
6
"""Builder behavior for binary package builds."""
7
8
__metaclass__ = type
9
10
__all__ = [
11
    'BinaryPackageBuildBehavior',
12
    ]
13
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
14
from twisted.internet import defer
10130.2.2 by William Grant
Move updateBuild(_WAITING) to the builder behaviour.
15
from zope.interface import implements
16
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
17
from canonical.launchpad.webapp import urlappend
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
18
from lp.buildmaster.interfaces.builder import CannotBuild
7675.420.1 by Michael Nelson
Initial IBuildFarmJobBehavior implementation for binary packages.
19
from lp.buildmaster.interfaces.buildfarmjobbehavior import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
20
    IBuildFarmJobBehavior,
21
    )
22
from lp.buildmaster.model.buildfarmjobbehavior import BuildFarmJobBehaviorBase
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
23
from lp.registry.interfaces.pocket import PackagePublishingPocket
24
from lp.soyuz.adapters.archivedependencies import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
25
    get_primary_current_component,
26
    get_sources_list_for_building,
27
    )
11411.6.2 by Julian Edwards
Change code imports for ArchivePurpose and ArchiveStatus
28
from lp.soyuz.enums import ArchivePurpose
7675.420.1 by Michael Nelson
Initial IBuildFarmJobBehavior implementation for binary packages.
29
30
7675.420.10 by Michael Nelson
Removed the behavior factory in favour of a zcml adapter.
31
class BinaryPackageBuildBehavior(BuildFarmJobBehaviorBase):
7675.420.1 by Michael Nelson
Initial IBuildFarmJobBehavior implementation for binary packages.
32
    """Define the behavior of binary package builds."""
33
34
    implements(IBuildFarmJobBehavior)
35
10130.1.7 by Jonathan Lange
Don't pass build_queue_item when it's not needed.
36
    def logStartBuild(self, logger):
7675.421.1 by Michael Nelson
Style changes and whitespace removal after gmb's review.
37
        """See `IBuildFarmJobBehavior`."""
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
38
        spr = self.build.source_package_release
7675.420.6 by Michael Nelson
Added an idle behavior, and moved things into more sane locations.
39
        logger.info("startBuild(%s, %s, %s, %s)", self._builder.url,
10130.1.5 by Jonathan Lange
We already know the IBuild, so no need to figure it out with queries.
40
                    spr.name, spr.version, self.build.pocket.title)
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
41
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
42
    def _buildFilemapStructure(self, ignored, logger):
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
43
        # Build filemap structure with the files required in this build
44
        # and send them to the slave.
45
        # If the build is private we tell the slave to get the files from the
46
        # archive instead of the librarian because the slaves cannot
47
        # access the restricted librarian.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
48
        dl = []
10130.1.5 by Jonathan Lange
We already know the IBuild, so no need to figure it out with queries.
49
        private = self.build.archive.private
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
50
        if private:
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
51
            dl.extend(self._cachePrivateSourceOnSlave(logger))
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
52
        filemap = {}
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
53
        for source_file in self.build.source_package_release.files:
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
54
            lfa = source_file.libraryfile
55
            filemap[lfa.filename] = lfa.content.sha1
56
            if not private:
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
57
                dl.append(
58
                    self._builder.slave.cacheFile(
59
                        logger, source_file.libraryfile))
60
        d = defer.gatherResults(dl)
61
        return d.addCallback(lambda ignored: filemap)
62
63
    def dispatchBuildToSlave(self, build_queue_id, logger):
64
        """See `IBuildFarmJobBehavior`."""
65
66
        # Start the binary package build on the slave builder. First
67
        # we send the chroot.
68
        chroot = self.build.distro_arch_series.getChroot()
69
        d = self._builder.slave.cacheFile(logger, chroot)
70
        d.addCallback(self._buildFilemapStructure, logger)
71
72
        def got_filemap(filemap):
73
            # Generate a string which can be used to cross-check when obtaining
74
            # results so we know we are referring to the right database object in
75
            # subsequent runs.
76
            buildid = "%s-%s" % (self.build.id, build_queue_id)
77
            cookie = self.buildfarmjob.generateSlaveBuildCookie()
78
            chroot_sha1 = chroot.content.sha1
79
            logger.debug(
80
                "Initiating build %s on %s" % (buildid, self._builder.url))
81
82
            args = self._extraBuildArgs(self.build)
83
            d = self._builder.slave.build(
84
                cookie, "binarypackage", chroot_sha1, filemap, args)
85
            def got_build((status, info)):
86
                message = """%s (%s):
87
                ***** RESULT *****
88
                %s
89
                %s
90
                %s: %s
91
                ******************
92
                """ % (
93
                    self._builder.name,
94
                    self._builder.url,
95
                    filemap,
96
                    args,
97
                    status,
98
                    info,
99
                    )
100
                logger.info(message)
101
            return d.addCallback(got_build)
102
103
        return d.addCallback(got_filemap)
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
104
10130.1.7 by Jonathan Lange
Don't pass build_queue_item when it's not needed.
105
    def verifyBuildRequest(self, logger):
7675.420.23 by Michael Nelson
Moved IBuilder._verifyBuildRequest to IBuildFarmJobBehavior.verify_build_request.
106
        """Assert some pre-build checks.
107
108
        The build request is checked:
109
         * Virtualized builds can't build on a non-virtual builder
110
         * Ensure that we have a chroot
111
         * Ensure that the build pocket allows builds for the current
112
           distroseries state.
113
        """
10130.1.5 by Jonathan Lange
We already know the IBuild, so no need to figure it out with queries.
114
        build = self.build
11583.3.4 by Jonathan Lange
Review changes.
115
        if build.is_virtualized and not self._builder.virtualized:
11573.3.16 by Jonathan Lange
Add the first attempt at an integration test for the binary package build behaviour.
116
            raise AssertionError(
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
117
                "Attempt to build virtual item on a non-virtual builder.")
7675.420.23 by Michael Nelson
Moved IBuilder._verifyBuildRequest to IBuildFarmJobBehavior.verify_build_request.
118
119
        # Assert that we are not silently building SECURITY jobs.
120
        # See findBuildCandidates. Once we start building SECURITY
121
        # correctly from EMBARGOED archive this assertion can be removed.
122
        # XXX Julian 2007-12-18 spec=security-in-soyuz: This is being
123
        # addressed in the work on the blueprint:
124
        # https://blueprints.launchpad.net/soyuz/+spec/security-in-soyuz
125
        target_pocket = build.pocket
126
        assert target_pocket != PackagePublishingPocket.SECURITY, (
127
            "Soyuz is not yet capable of building SECURITY uploads.")
128
129
        # Ensure build has the needed chroot
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
130
        chroot = build.distro_arch_series.getChroot()
7675.420.23 by Michael Nelson
Moved IBuilder._verifyBuildRequest to IBuildFarmJobBehavior.verify_build_request.
131
        if chroot is None:
132
            raise CannotBuild(
133
                "Missing CHROOT for %s/%s/%s" % (
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
134
                    build.distro_series.distribution.name,
135
                    build.distro_series.name,
136
                    build.distro_arch_series.architecturetag))
7675.420.23 by Michael Nelson
Moved IBuilder._verifyBuildRequest to IBuildFarmJobBehavior.verify_build_request.
137
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
138
        # This should already have been checked earlier, but just check again
10130.7.32 by Jelmer Vernooij
Factor out checks for allowing uploads to a pocket.
139
        # here in case of programmer errors.
7675.687.129 by Michael Nelson
Fixed test_manager.py
140
        reason = build.archive.checkUploadToPocket(
141
            build.distro_series,
10156.2.20 by Jelmer Vernooij
merge devel
142
            build.pocket)
10130.7.35 by Jelmer Vernooij
More review feedback from jono.
143
        assert reason is None, (
144
                "%s (%s) can not be built for pocket %s: invalid pocket due "
10677.2.1 by Jeroen Vermeulen
Replace slave build id with slave build cookie.
145
                "to the series status of %s." %
10130.7.35 by Jelmer Vernooij
More review feedback from jono.
146
                    (build.title, build.id, build.pocket.name,
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
147
                     build.distro_series.name))
7675.420.23 by Michael Nelson
Moved IBuilder._verifyBuildRequest to IBuildFarmJobBehavior.verify_build_request.
148
10604.4.4 by William Grant
IBFJB.slaveStatus -> updateSlaveStatus; no longer returns the updated dict.
149
    def updateSlaveStatus(self, raw_slave_status, status):
10604.4.1 by William Grant
Move the common IBFJB.slaveStatus components into Builder.slaveStatus.
150
        """Parse the binary build specific status info into the status dict.
7675.420.31 by Michael Nelson
Moved binary build specific code from IBuilder.slaveStatus().
151
152
        This includes:
10130.8.2 by Michael Nelson
Moved _handleStatus_OK from IBuild to BuildBase as it's common between SPRecipe builds and binary builds. Also added slaveStatus() to the RecipeBuildBehavior.
153
        * filemap => dictionary or None
7675.420.31 by Michael Nelson
Moved binary build specific code from IBuilder.slaveStatus().
154
        * dependencies => string or None
155
        """
10604.4.1 by William Grant
Move the common IBFJB.slaveStatus components into Builder.slaveStatus.
156
        build_status_with_files = (
157
            'BuildStatus.OK',
158
            'BuildStatus.PACKAGEFAIL',
159
            'BuildStatus.DEPFAIL',
160
            )
161
        if (status['builder_status'] == 'BuilderStatus.WAITING' and
162
            status['build_status'] in build_status_with_files):
163
            status['filemap'] = raw_slave_status[3]
164
            status['dependencies'] = raw_slave_status[4]
7675.420.31 by Michael Nelson
Moved binary build specific code from IBuilder.slaveStatus().
165
10130.1.6 by Jonathan Lange
Don't need build_queue_item to store files.
166
    def _cachePrivateSourceOnSlave(self, logger):
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
167
        """Ask the slave to download source files for a private build.
168
169
        :param logger: A logger used for providing debug information.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
170
        :return: A list of Deferreds, each of which represents a request
171
            to cache a file.
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
172
        """
173
        # The URL to the file in the archive consists of these parts:
174
        # archive_url / makePoolPath() / filename
175
        # Once this is constructed we add the http basic auth info.
176
177
        # Avoid circular imports.
178
        from lp.soyuz.model.publishing import makePoolPath
179
10130.1.5 by Jonathan Lange
We already know the IBuild, so no need to figure it out with queries.
180
        archive = self.build.archive
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
181
        archive_url = archive.archive_url
10130.1.5 by Jonathan Lange
We already know the IBuild, so no need to figure it out with queries.
182
        component_name = self.build.current_component.name
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
183
        dl = []
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
184
        for source_file in self.build.source_package_release.files:
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
185
            file_name = source_file.libraryfile.filename
186
            sha1 = source_file.libraryfile.content.sha1
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
187
            spn = self.build.source_package_release.sourcepackagename
10130.1.24 by Jonathan Lange
Fix failing tests.
188
            poolpath = makePoolPath(spn.name, component_name)
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
189
            url = urlappend(archive_url, poolpath)
190
            url = urlappend(url, file_name)
191
            logger.debug("Asking builder on %s to ensure it has file %s "
7675.420.22 by Michael Nelson
Fixed a few wrong references to self in BinaryPackageBuildBehavior.
192
                         "(%s, %s)" % (
193
                            self._builder.url, file_name, url, sha1))
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
194
            dl.append(
195
                self._builder.slave.sendFileToSlave(
196
                    sha1, url, "buildd", archive.buildd_secret))
197
        return dl
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
198
7675.420.26 by Michael Nelson
Un-pep08'd method names in the behavior classes.
199
    def _extraBuildArgs(self, build):
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
200
        """
201
        Return the extra arguments required by the slave for the given build.
202
        """
203
        # Build extra arguments.
204
        args = {}
205
        # turn 'arch_indep' ON only if build is archindep or if
206
        # the specific architecture is the nominatedarchindep for
207
        # this distroseries (in case it requires any archindep source)
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
208
        args['arch_indep'] = build.distro_arch_series.isNominatedArchIndep
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
209
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
210
        suite = build.distro_arch_series.distroseries.name
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
211
        if build.pocket != PackagePublishingPocket.RELEASE:
212
            suite += "-%s" % (build.pocket.name.lower())
213
        args['suite'] = suite
214
11121.3.2 by William Grant
Send arch_tag for all existing job types, and fix broken tests.
215
        args['arch_tag'] = build.distro_arch_series.architecturetag
216
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
217
        archive_purpose = build.archive.purpose
218
        if (archive_purpose == ArchivePurpose.PPA and
219
            not build.archive.require_virtualized):
220
            # If we're building a non-virtual PPA, override the purpose
221
            # to PRIMARY and use the primary component override.
222
            # This ensures that the package mangling tools will run over
223
            # the built packages.
224
            args['archive_purpose'] = ArchivePurpose.PRIMARY.name
225
            args["ogrecomponent"] = (
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
226
                get_primary_current_component(build.archive,
227
                    build.distro_series, build.source_package_release.name))
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
228
        else:
229
            args['archive_purpose'] = archive_purpose.name
230
            args["ogrecomponent"] = (
231
                build.current_component.name)
232
7675.687.92 by Michael Nelson
Changes for buildd-dispatching.txt
233
        args['archives'] = get_sources_list_for_building(build,
234
            build.distro_arch_series, build.source_package_release.name)
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
235
        args['archive_private'] = build.archive.private
7675.767.7 by William Grant
Merge devel.
236
        args['build_debug_symbols'] = build.archive.build_debug_symbols
237
7675.420.21 by Michael Nelson
Factored out dispatchBuildToSlave, cachePrivateSourceOnSlave and soyuz-specific argument creation to BinaryPackageBuildBehavior.
238
        return args