From owner-svn-src-projects@FreeBSD.ORG Fri Apr 22 19:03:33 2011
Return-Path:
Delivered-To: svn-src-projects@freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
by hub.freebsd.org (Postfix) with ESMTP id AB155106566C;
Fri, 22 Apr 2011 19:03:33 +0000 (UTC) (envelope-from flz@FreeBSD.org)
Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c])
by mx1.freebsd.org (Postfix) with ESMTP id 98FA68FC16;
Fri, 22 Apr 2011 19:03:33 +0000 (UTC)
Received: from svn.freebsd.org (localhost [127.0.0.1])
by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p3MJ3XL0054440;
Fri, 22 Apr 2011 19:03:33 GMT (envelope-from flz@svn.freebsd.org)
Received: (from flz@localhost)
by svn.freebsd.org (8.14.3/8.14.3/Submit) id p3MJ3XDF054432;
Fri, 22 Apr 2011 19:03:33 GMT (envelope-from flz@svn.freebsd.org)
Message-Id: <201104221903.p3MJ3XDF054432@svn.freebsd.org>
From: Florent Thoumie
Date: Fri, 22 Apr 2011 19:03:33 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-projects@freebsd.org
X-SVN-Group: projects
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Cc:
Subject: svn commit: r220956 - in projects/portbuild: . conf errorlogs
scripts
X-BeenThere: svn-src-projects@freebsd.org
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: "SVN commit messages for the src " projects"
tree"
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Fri, 22 Apr 2011 19:03:33 -0000
Author: flz
Date: Fri Apr 22 19:03:33 2011
New Revision: 220956
URL: http://svn.freebsd.org/changeset/base/220956
Log:
Import portbuild from pcvs.
Discussed with: portmgr (linimon, pav, self)
Added:
projects/portbuild/
projects/portbuild/conf/
projects/portbuild/conf/README.dotunnel
projects/portbuild/conf/client.conf
projects/portbuild/conf/common.conf
projects/portbuild/conf/make.conf
projects/portbuild/conf/server.conf
projects/portbuild/errorlogs/
projects/portbuild/errorlogs/index.shtml
projects/portbuild/scripts/
projects/portbuild/scripts/allgohans (contents, props changed)
projects/portbuild/scripts/allgohans.safe (contents, props changed)
projects/portbuild/scripts/bothlogs (contents, props changed)
projects/portbuild/scripts/build (contents, props changed)
projects/portbuild/scripts/buildenv
projects/portbuild/scripts/buildfailure (contents, props changed)
projects/portbuild/scripts/buildproxy (contents, props changed)
projects/portbuild/scripts/buildproxy-client (contents, props changed)
projects/portbuild/scripts/buildscript (contents, props changed)
projects/portbuild/scripts/buildsuccess (contents, props changed)
projects/portbuild/scripts/checkmachines (contents, props changed)
projects/portbuild/scripts/checkmachines.sh (contents, props changed)
projects/portbuild/scripts/chopindex (contents, props changed)
projects/portbuild/scripts/claim-chroot (contents, props changed)
projects/portbuild/scripts/clean-chroot (contents, props changed)
projects/portbuild/scripts/cleanup-chroots (contents, props changed)
projects/portbuild/scripts/client-metrics (contents, props changed)
projects/portbuild/scripts/comparelogs (contents, props changed)
projects/portbuild/scripts/cpdistfiles (contents, props changed)
projects/portbuild/scripts/cppackages (contents, props changed)
projects/portbuild/scripts/do-cleanup-chroots (contents, props changed)
projects/portbuild/scripts/docppackages (contents, props changed)
projects/portbuild/scripts/dodistfiles (contents, props changed)
projects/portbuild/scripts/dologs (contents, props changed)
projects/portbuild/scripts/dopackages (contents, props changed)
projects/portbuild/scripts/dopackages.wrapper (contents, props changed)
projects/portbuild/scripts/dopackages2 (contents, props changed)
projects/portbuild/scripts/dopackagestats (contents, props changed)
projects/portbuild/scripts/dosetupnode (contents, props changed)
projects/portbuild/scripts/flushsquid (contents, props changed)
projects/portbuild/scripts/keeprestr (contents, props changed)
projects/portbuild/scripts/makeduds (contents, props changed)
projects/portbuild/scripts/makeindex (contents, props changed)
projects/portbuild/scripts/makerestr (contents, props changed)
projects/portbuild/scripts/makeworld (contents, props changed)
projects/portbuild/scripts/mkbindist (contents, props changed)
projects/portbuild/scripts/nukesquid (contents, props changed)
projects/portbuild/scripts/packagebuild (contents, props changed)
projects/portbuild/scripts/pdispatch (contents, props changed)
projects/portbuild/scripts/pnohang.c
projects/portbuild/scripts/pollmachine (contents, props changed)
projects/portbuild/scripts/portbuild (contents, props changed)
projects/portbuild/scripts/processfail (contents, props changed)
projects/portbuild/scripts/processlogs (contents, props changed)
projects/portbuild/scripts/processlogs2 (contents, props changed)
projects/portbuild/scripts/processonelog (contents, props changed)
projects/portbuild/scripts/prunebad
projects/portbuild/scripts/prunefailure (contents, props changed)
projects/portbuild/scripts/prunepkgs (contents, props changed)
projects/portbuild/scripts/ptimeout.c
projects/portbuild/scripts/releasemachine (contents, props changed)
projects/portbuild/scripts/reportload (contents, props changed)
projects/portbuild/scripts/reportload.sh (contents, props changed)
projects/portbuild/scripts/retcodes
projects/portbuild/scripts/setupnode (contents, props changed)
projects/portbuild/scripts/showrunning (contents, props changed)
projects/portbuild/scripts/stats (contents, props changed)
projects/portbuild/scripts/straslivy.py (contents, props changed)
projects/portbuild/scripts/updatesnap (contents, props changed)
projects/portbuild/scripts/updatesnap.ports (contents, props changed)
projects/portbuild/scripts/zbackup (contents, props changed)
projects/portbuild/scripts/zclient (contents, props changed)
projects/portbuild/scripts/zexpire
Added: projects/portbuild/conf/README.dotunnel
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/conf/README.dotunnel Fri Apr 22 19:03:33 2011 (r220956)
@@ -0,0 +1,32 @@
+Various package build nodes require us to set up TCP tunnels to talk
+to them. (Some systems don't pass certain ports; some systems have
+firewalls; some systems have multiple nodes on one IP address.)
+
+These have always been hardcoded in crontab lines of the form "while true;
+do ; done". Other than the magic hardcoding,
+there's a problem with this. When the tunnel command exits, such as if
+the host suddenly becoming unreachable, it doesn't send mail -- instead
+it just accumulates a huge file in /var/spool/clientmqueue which never
+gets sent. To add insult to injury, /var is on the root partition on
+pointyhat.
+
+To cure these problems, we now have
+
+ /var/portbuild/conf//dotunnel.XXX
+
+where XXX corresponds to one line in the old crontab. Each script sets
+up one tunnel, sends mail to the user(s) in
+
+ /var/portbuild//portbuild.conf
+
+once the command exits, and then sleeps.
+
+Why not put it in /var/portbuild/ you ask? That directory is
+propogated to all nodes for that arch. This would be a security leak.
+The intention is that none of the dotunnel files will be checked into
+CVS.
+
+Final note: each script figures out which arch it is for by fiddling
+with its $0, so invoke it with its full pathname.
+
+mcl
Added: projects/portbuild/conf/client.conf
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/conf/client.conf Fri Apr 22 19:03:33 2011 (r220956)
@@ -0,0 +1,41 @@
+#
+# client-side definitions (used in /var/portbuild/scripts/portbuild)
+#
+# $FreeBSD: ports/Tools/portbuild/conf/client.conf,v 1.4 2011/01/23 02:34:58 linimon Exp $
+#
+
+#
+# items to be customized per each package build master
+#
+
+# for nodes where disconnected=0, the NFS host they should mount ports/
+# and src/ from
+CLIENT_NFS_MASTER=pointyhat.FreeBSD.org
+
+# fallback for distfiles (see make.conf in bindist-*.tar)
+CLIENT_BACKUP_FTP_SITE=pointyhat.FreeBSD.org
+
+# where completed packages get uploaded
+CLIENT_UPLOAD_HOST=pointyhat.FreeBSD.org
+
+#
+# items that will most likely be common to all package build masters
+#
+
+CLIENT_DISTDIR=/tmp/distfiles
+# XXX renaming this from PACKAGES
+CLIENT_PACKAGES_LOCATION=/tmp/packages
+CLIENT_SRCBASE=/usr/src
+CLIENT_WRKDIRPREFIX=/work
+
+# wait 2 hours before killing build with no output
+CLIENT_BUILD_TIMEOUT=7200
+CLIENT_FTP_TIMEOUT=900
+CLIENT_HTTP_TIMEOUT=900
+
+# to prevent runaway processes -- 400 meg file size limit, 2 hours CPU limit
+CLIENT_ULIMIT_F=819200
+CLIENT_ULIMIT_T=7200
+
+# debugging definitions
+CLIENT_MALLOC_OPTIONS=AJ
Added: projects/portbuild/conf/common.conf
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/conf/common.conf Fri Apr 22 19:03:33 2011 (r220956)
@@ -0,0 +1,21 @@
+#
+# package building configuration file containing things that are common
+# both to the server-side (pointyhat instance) and the client side
+# (individual build clients).
+#
+# original author: linimon
+#
+# $FreeBSD: ports/Tools/portbuild/conf/common.conf,v 1.1 2010/12/01 02:35:20 linimon Exp $
+#
+
+#
+# top-level package building things. These will probably be common
+# to all package build masters.
+#
+
+LOCALBASE=/usr/local
+PKGSUFFIX=.tbz
+
+ARCHS_REQUIRING_AOUT_COMPAT="i386"
+ARCHS_REQUIRING_LINPROCFS="amd64 i386"
+ARCHS_SUPPORTING_COMPAT_IA32="amd64 i386 ia64"
Added: projects/portbuild/conf/make.conf
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/conf/make.conf Fri Apr 22 19:03:33 2011 (r220956)
@@ -0,0 +1,16 @@
+# DON'T SET PORT VARIABLES UNCONDITIONALLY - THEY NEED TO BE
+# OVERRIDABLE BY THE SCRIPTS
+USA_RESIDENT?=YES
+
+#
+MASTER_SITE_BACKUP= \
+ ftp://ftp-master.freebsd.org/pub/FreeBSD/ports/distfiles/${DIST_SUBDIR}/
+MASTER_SITE_OVERRIDE?= ${MASTER_SITE_BACKUP}
+MASTER_SITE_LOCAL= \
+ ftp://ftp-master.FreeBSD.org/pub/FreeBSD/ports/local-distfiles/%SUBDIR%/
+
+NO_PROFILE=true
+MAKE_KERBEROS5= yes
+SENDMAIL_CF= freefall.cf
+BOOT_PXELDR_PROBE_KEYBOARD= true
+ENABLE_SUID_K5SU=yes
Added: projects/portbuild/conf/server.conf
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/conf/server.conf Fri Apr 22 19:03:33 2011 (r220956)
@@ -0,0 +1,105 @@
+#
+# package building configuration file (server-side). Specific to each
+# pointyhat instance.
+#
+# note: readable by both Python and /bin/sh files. HOWEVER, there is no
+# code yet to do the {}-style shell expansions in the Python scripts.
+# Beware!
+#
+# original author: linimon
+#
+# $FreeBSD: ports/Tools/portbuild/conf/server.conf,v 1.7 2011/04/22 18:32:13 linimon Exp $
+#
+
+#
+# top-level package building things
+#
+
+SUPPORTED_ARCHS="amd64 i386 ia64 powerpc sparc64"
+
+SRC_BRANCHES="7 8 9"
+SRC_BRANCHES_PATTERN="^[0-9]*"
+SRC_BRANCH_7_TAG=RELENG_7_3
+SRC_BRANCH_8_TAG=RELENG_8_1
+SRC_BRANCH_9_TAG=.
+
+DEFAULT_LINUX_OSRELEASE="2.6.16"
+
+#
+# directory management definitions
+#
+
+ZFS_VOLUME=a
+ZFS_MOUNTPOINT=/a
+
+SNAP_DIRECTORY=snap
+SNAP_PORTS_DIRECTORY=${SNAP_DIRECTORY}/ports-head
+SNAP_SRC_DIRECTORY_PREFIX=${SNAP_DIRECTORY}/src-
+
+SUPFILE_DIRECTORY=/home/portmgr/sup
+PORTS_MASTER_SUPFILE=${SUPFILE_DIRECTORY}/ports-master-supfile
+SRC_MASTER_SUPFILE=${SUPFILE_DIRECTORY}/src-master-supfile
+PORTS_SUPFILE=${SUPFILE_DIRECTORY}/ports-supfile
+SRC_SUPFILE=${SUPFILE_DIRECTORY}/src-supfile
+
+WORLDDIR=${ZFS_MOUNTPOINT}/chroot/
+
+# XXX TODO (note: Python script, so avoid {})
+#zbackup a/nfs a/local a/portbuild/* /dumpster
+#zexpire a/nfs a/local a/portbuild/* a/snap/*
+
+#
+# buildproxy definitions (note: Python script, so avoid {})
+#
+
+BUILDPROXY_SOCKET_FILE=/tmp/.build
+
+#
+# pdispatch definitions
+#
+
+# reflect hardwiring in 'buildscript' phase 1 and also 'processonelog' and
+# 'processlogs2'. You probably do not want to change this!
+PDISPATCH_HDRLENGTH=6
+
+# number of lines of log to email
+PDISPATCH_LOGLENGTH=1000
+
+# wait 100 hours maximum
+PDISPATCH_TIMEOUT=360000
+
+#
+# qmanager definitions (note: Python script, so avoid {})
+#
+
+QMANAGER_PATH=/var/portbuild/evil/qmanager
+QMANAGER_DATABASE_FILE=qdb.sl3
+QMANAGER_SOCKET_FILE=/tmp/.qmgr
+
+QMANAGER_PRIORITY_PACKAGES="openoffice kde-3"
+
+# maximum number of times to build an individual job
+QMANAGER_MAX_JOB_ATTEMPTS=5
+
+# attempt to limit the amount time (and email) on botched runs
+QMANAGER_RUNAWAY_PERCENTAGE=0.75
+QMANAGER_RUNAWAY_THRESHOLD=100
+
+#
+# upload definitions (see 'cpdistfiles')
+#
+
+UPLOAD_DIRECTORY="w/ports/distfiles/"
+UPLOAD_TARGET="ftp-master.FreeBSD.org"
+UPLOAD_USER="portmgr"
+
+#
+# user-visible things
+#
+
+MASTER_URL="pointyhat.FreeBSD.org"
+
+#
+# www definitions (see processfail)
+#
+WWW_DIRECTORY=/usr/local/www/data/
Added: projects/portbuild/errorlogs/index.shtml
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/errorlogs/index.shtml Fri Apr 22 19:03:33 2011 (r220956)
@@ -0,0 +1,984 @@
+
+
+
+
+FreeBSD Package building logs and errors
+
+
+FreeBSD Package building logs and errors
+
+FreeBSD maintains a build farm (the "pointyhat cluster") that is used
+to build all packages across all supported architectures and major releases.
+This page contains the build logs and errors for all the ports built by
+the cluster. See the notes for additional information,
+or the types of package errors detected.
+
+
+Port cross-reference summaries
+
+These live on
+portsmon.FreeBSD.org.
+
+
+- Build errors
+by portname;
+by portname vs. build environment;
+by error type vs. build environment
+- Problem Reports
+for existing ports;
+for new ports;
+for the ports framework;
+for repocopies requested;
+for unknown
+- Build Errors and
+Problem Reports
+by portname;
+for one maintainer;
+for broken ports;
+for deprecated ports;
+for forbidden ports
+- Everything about
+one port
+- The
+complete list of all reports
+
+
+
+New build failures
+
+Check here to find the most recent error log from your port.
+
+
+
+
+-
+ New build
+failures on 7.x-stable:
+amd64
+i386
+ia64
+sparc64
+
+ New build
+failures on 8.x-stable:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+ New build
+failures on 9.x-current:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+
+ New build failures on 7.x-stable with experimental port patches:
+amd64
+i386
+
+ New build failures on 8.x-stable with experimental port patches:
+amd64
+i386
+
+ New build failures on 9.x-current with experimental port patches:
+amd64
+i386
+
+
+
+
+
+Error logs
+
+
+
+-
+ Previous run
+on 7.x-stable:
+amd64
+i386
+ia64
+sparc64
+
+ Current run
+on 7.x-stable:
+amd64
+i386
+ia64
+sparc64
+
+ Previous run
+on 8.x-stable:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+ Current run
+on 8.x-stable:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+ Previous run
+on 9.x-current:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+ Current run
+on 9.x-current:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+
+ Previous run
+on 7.x-stable with experimental port patches:
+amd64
+i386
+
+ Current run
+on 7.x-stable with experimental port patches:
+amd64
+i386
+
+ Previous run
+on 8.x-stable with experimental port patches:
+amd64
+i386
+
+ Current run
+on 8.x-stable with experimental port patches:
+amd64
+i386
+
+ Previous run
+on 9.x-current with experimental port patches:
+amd64
+i386
+
+ Current run
+on 9.x-current with experimental port patches:
+amd64
+i386
+
+
+
+
+Build logs (errors and otherwise)
+
+
+
+-
+Previous run
+on 7.x-stable:
+amd64
+i386
+ia64
+sparc64
+
+Current run on
+7.x-stable:
+amd64
+i386
+ia64
+sparc64
+
+Previous run
+on 8.x-stable:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+Current run on
+8.x-stable:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+Previous run
+on 9.x-current:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+Current run on
+9.x-current:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+
+Previous run
+on 7.x-stable with experimental port patches:
+amd64
+i386
+
+Current run on
+7.x-stable with experimental port patches:
+amd64
+i386
+
+Previous run
+on 8.x-stable with experimental port patches:
+amd64
+i386
+
+Current run on
+8.x-stable with experimental port patches:
+amd64
+i386
+
+Previous run
+on 9.x-current with experimental port patches:
+amd64
+i386
+
+Current run on
+9.x-current with experimental port patches:
+amd64
+i386
+
+
+
+
+
+Packages
+
+
+
+-
+ Packages from
+latest run on 6-stable:
+amd64
+i386
+sparc64
+
+ Packages from
+latest run on 7-stable:
+amd64
+i386
+ia64
+sparc64
+
+ Packages from
+latest run on 8-stable:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+ Packages from
+latest run on 9-current:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+
+ Package
+building statistics (current state of all package builds)
+
+
+
+
+Archive
+
+
+
+- All error
+logs:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+ All portbuild
+logs:
+amd64
+i386
+ia64
+powerpc
+sparc64
+
+
+
+
+Additional information
+
+
+All of the "Current run" links are possibly in progress and may be
+partial, so keep that in mind if there appear to be some missing.
+
+None of the ports marked IS_INTERACTIVE or
+NO_PACKAGE are built any more -- if you have ports that
+fall into those categories, assume their packages or distfiles will
+never show up in ftp sites or CDROMs. RESTRICTED packages
+are built and deleted (using "make
+clean-restricted-list"). NO_CDROM packages are built
+but deleted (using "make clean-cdrom-list") before being
+put on a CDROM.
+
+See also the types of errors detected.
+
+Notes on the building process:
+
+
+- Every port is built in its own chroot environment
+
+, starting with an
+empty /usr/local and /usr/X11R6. The dependencies are installed as packages just before
+the build. You can see the list of dependencies on the third line
+of the log -- the "foo.tgz bar.tgz" stuff are the dependencies. To
+make sure that these actually work, DEPENDS_TARGET is set
+to "/usr/bin/true"; if you see "/usr/bin/true is up to date" or
+some such, that means there is something wrong with the dependency
+lines or the packages this port is depending on.
+
+- The build is done on a shared (read-only) /usr/ports
+with
+WRKDIRPREFIX set to /work. If your
+WRKSRC looks funny, that's probably why.
+
+- MASTER_SITE_OVERRIDE is pointing to pointyhat's distfile
+dir, and MASTER_SITE_BACKUP is pointing to
+ftp-master.freebsd.org or a local mirror.
+Please pay attention to
+
+Emanuel Haupt's distfile checker
+for that.
+
+- The ports are built on machines that are mostly running
+ 9-CURRENT, with some 8.x-STABLE machines. If your port depends on
+ the result of uname(3) or sysctl to determine the running version of
+ FreeBSD, change it to use uname(1) instead (the builds use a dummy
+ uname(1) that reports the target version of FreeBSD), or change it to
+ use the value of the OSVERSION variable that can be passed in from
+ the port makefile.
+
+
+Types of package errors detected
+
+Here is the alphabetical list of current errors
+detected by the AI script. Note that this is all just a rough guess --
+it is merely for your aid.
+
+Key:
+
+ - The most common
+ errors.
+ - Some less common
+ errors.
+ - Transient
+ errors. These may not be your fault.
+
+
+
+
+
+- arch
+
+- The port does not build on a particular architecture, due to
+assembler or linker errors. In some easy cases this is due to
+not picking up the various ARCH configuration variables
+in the Makefile; you'll see this via, e.g., a Sparc make
+failing while looking for an i386 subdirectory. For the 64-bit
+architectures, a common problem is the assumption many programmers
+make that pointers may be cast to and from 32-bit ints. In other cases
+the problems run much deeper, in which case ONLY_FOR_ARCHS
+may be needed.
+
+- autoconf
+
+- Your port depends on autoconf, but the Makefile
+either doesn't have USE_AUTOCONF, or does not use
+USE_AUTOCONF_VER correctly.
+
+- autoheader
+
+- Your port depends on autoheader, but the Makefile
+cannot find it; set USE_AUTOHEADER.
+
+- automake
+
+- Your port depends on automake, but the Makefile
+either doesn't have USE_AUTOMAKE, or does not use
+USE_AUTOMAKE_VER correctly.
+
+- bad C++ code
+
+- There is a compiler error which is caused by something specific
+to C++.
+
+- compiler error
+
+- There is a C compiler error which is caused by something other
+than e.g. "new compiler error".
+
+- CATEGORIES
+
+- The CATEGORIES line in Makefile includes an
+invalid category.
+
+- checksum
+
+- The checksum of one or more of the files is incorrect.
+
+- clang
+
+- Your code does not run with the the experimental clang compiler. See
+(TBA)
+for further information.
+
+- clang bug
+
+- You have tickled a bug in clang itself. See
+(TBA)
+for further information.
+
+- cluster
+
+- There was some kind of transient error on the build cluster. It is not your
+fault.
+
+- compat6x
+
+- This port needs to depend on a port misc/compat6x.
+
+- configure error
+
+- The port's configure script produced some kind of
+error.
+(Note: using clang as the ports compiler can also trigger this message.)
+
+- coredump
+
+- Some process in the build chain dropped core. While your port may indeed
+be faulty, the process that dropped core should also be fixed.
+
+- cpusetsize
+
+- This port needs to catch up with the cpusetsize sysctl change in 9-CURRENT.
+
+- depend object
+
+- The port is trying to reinstall a dependency that already
+exists. This is usually caused by the first field of a
+*_DEPENDS line (the obj of
+obj:dir[:target]) indicating a file that is not installed
+by the dependency, causing it to be rebuilt even though it has
+already been added from a package.
+
+- depend package
+
+- There was an error during adding dependencies
+from packages. It is the fault of the package being added, not
+this port.
+
+- dirent
+
+- The port has not caught up with the change to
scandir(3)
+as committed in FreeBSD version 800501.
+
+- disk full
+
+- The disk filled up on the build system. It is not your
+fault.
+
+- DISPLAY
+
+- This port requires an X display to build. There is nothing you
+can do about it unless you can somehow make it not require an X
+connection.
+
+- distinfo update
+
+- The contents of distinfo does not match the list of
+distfiles or patchfiles.
+
+- fetch
+
+- One or more of the files could not be fetched.
+
+- fetch timeout
+
+- Your fetch process was killed because it took too long. (More
+accurately, it did not produce any output for a long time.) Please
+put sites with better connectivity near the beginning of
+MASTER_SITES.
+
+- forbidden
+
+- Someone has marked this port as "forbidden", almost always due
+to security concerns. See the logfile for more information.
+
+- gcc bug
+
+- You have tickled a bug in gcc itself. See the
+GNU bug report documentation
+for further information.
+
+- gcc4
+
+- Your code does not run with the latest gcc version
+See the wiki page
+for further information.
+
+- gmake
+
+- Your code does not run with the latest, incompatible, gmake version
+(3.82.)
+
+- install error
+
+- There was an error during installation.
+
+- LIB_DEPENDS
+
+- The LIB_DEPENDS line specifies a library name
+incorrectly. This often happens when a port is upgraded and the
+shared library version number changes.
+
+- linker error
+
+- There is a linker error which is caused by something other than
+those flagged elsewhere.
+(Note: using clang as the ports compiler can also trigger this message.)
+
+- makefile
+
+- There is an error in the Makefile, possibly in the default
+targets.
+
+- manpage
+
+- There is a manpage listed in a MAN? macro that does not
+exist or is not installed in the right place.
+
+- missing header
+
+- There is a missing header file. This is usually caused by
+either (1) a missing dependency, or (2) specifying an incorrect
+location with -I in the compiler command line.
+
+- mtree
+
+- The port leaves ${PREFIX} in a state that is not
+consistent with the mtree definition after pkg_delete. This
+usually means some files are missing from PLIST. It could
+also mean that your installation scripts create files or
+directories not properly deleted by the deinstallation scripts.
+Another possibility is that your port is deleting some directories
+it is not supposed to, or incorrectly modifying some directory's
+permission.
+
+- nested_declaration
+
+- There is a nested declaration in the source code.
+
+- new compiler error
+
+- The newest version of gcc in the base does not like the source code. This is
+usually due to stricter C++ type checking or changes in register
+allocation policy.
+
+- NFS
+
+- There was either a temporary NFS error on the build system
+(which is not your fault), or the WRKSRC is invalid
+(which is your fault).
+
+- patch
+
+- One or more of the patches failed.
+
+- perl
+
+- perl is no longer included by default in the base
+system, but your port's configuration process depends on it. While
+this change helps avoid having a stale version of perl
+in the base system, it also means that many ports now need to include
+USE_PERL5.
+
+- PLIST
+
+- There is a missing item in the PLIST. Note that this is
+often caused by an earlier error that went undetected. In this case,
+you should fix the error and also the build process so it will fail
+upon an error instead of continuing, since that makes debugging
+that much harder.
+
+- process failed
+
+- The make process terminated unexpectedly, due to
+something like a signal 11 or bus error.
+
+- runaway process
+
+- Your make package process was killed because it took
+too long. (More accurately, it did not produce any output for a long
+time.) It is probably because there is a process spinning in an infinite
+loop. Please check the log to determine the exact cause of the
+problem.
+
+- segfault
+
+- Some process in the build chain got a segmentation fault.
+
+- sem_wait
+
+- This port needs to catch up with semaphore changes in 9-CURRENT.
+
+- termios
+
+- This port needs to catch up with the termios.h changes in src.
+
+- threads
+
+- There is a linker error which is caused by failing to find one of
+the thread libraries.
+
+- truncated_distfile
+
+- A package node encountered an error during pkg_add. It is not your
+fault. Linimon is trying to figure out this problem.
+
+- utmp_x
+
+- This port needs to catch up with the utmp_x.h changes in src.
+
+- WRKDIR
+
+- The port is attempting to change something outside
+${WRKDIR}. See handbook
+for details.
+
+- ??? (unknown)
+
+- The automated script cannot even guess what is wrong with your
+port. portmgr tries to keep the processonelog script
+reasonably efficient while covering as many errors as possible, but many
+errors are not common enough to try to catch.
+
+
+Here is an alphabetical list of obsolete errors
+that used to be detected by the AI script, but are now uncommon enough to
+be skipped:
+
+
+- alignment
+
+- You've managed to confuse the assembler with a misaligned
+structure.
+
+- apxs
+
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
From owner-svn-src-projects@FreeBSD.ORG Sat Apr 23 21:02:25 2011
Return-Path:
Delivered-To: svn-src-projects@freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
by hub.freebsd.org (Postfix) with ESMTP id E427C106566B;
Sat, 23 Apr 2011 21:02:25 +0000 (UTC) (envelope-from flz@FreeBSD.org)
Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c])
by mx1.freebsd.org (Postfix) with ESMTP id CDD5E8FC19;
Sat, 23 Apr 2011 21:02:25 +0000 (UTC)
Received: from svn.freebsd.org (localhost [127.0.0.1])
by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p3NL2Pr3003592;
Sat, 23 Apr 2011 21:02:25 GMT (envelope-from flz@svn.freebsd.org)
Received: (from flz@localhost)
by svn.freebsd.org (8.14.4/8.14.4/Submit) id p3NL2PpT003585;
Sat, 23 Apr 2011 21:02:25 GMT (envelope-from flz@svn.freebsd.org)
Message-Id: <201104232102.p3NL2PpT003585@svn.freebsd.org>
From: Florent Thoumie
Date: Sat, 23 Apr 2011 21:02:25 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-projects@freebsd.org
X-SVN-Group: projects
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Cc:
Subject: svn commit: r220976 - in projects/portbuild: conf qmanager scripts
X-BeenThere: svn-src-projects@freebsd.org
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: "SVN commit messages for the src " projects"
tree"
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Sat, 23 Apr 2011 21:02:26 -0000
Author: flz
Date: Sat Apr 23 21:02:25 2011
New Revision: 220976
URL: http://svn.freebsd.org/changeset/base/220976
Log:
Import qmanager into portbuild.
Added:
projects/portbuild/qmanager/
projects/portbuild/qmanager/acl.py
projects/portbuild/qmanager/dumpdb.py (contents, props changed)
projects/portbuild/qmanager/packagebuild (contents, props changed)
projects/portbuild/qmanager/qclient (contents, props changed)
projects/portbuild/qmanager/qmanager (contents, props changed)
projects/portbuild/qmanager/qmanager.py (contents, props changed)
projects/portbuild/qmanager/qmanagerclient.py
projects/portbuild/qmanager/qmanagerhandler.py
projects/portbuild/qmanager/qmanagerobj.py
projects/portbuild/qmanager/schema.sql
Modified:
projects/portbuild/conf/server.conf
projects/portbuild/scripts/dopackages
Modified: projects/portbuild/conf/server.conf
==============================================================================
--- projects/portbuild/conf/server.conf Sat Apr 23 20:59:58 2011 (r220975)
+++ projects/portbuild/conf/server.conf Sat Apr 23 21:02:25 2011 (r220976)
@@ -72,7 +72,6 @@ PDISPATCH_TIMEOUT=360000
# qmanager definitions (note: Python script, so avoid {})
#
-QMANAGER_PATH=/var/portbuild/evil/qmanager
QMANAGER_DATABASE_FILE=qdb.sl3
QMANAGER_SOCKET_FILE=/tmp/.qmgr
Added: projects/portbuild/qmanager/acl.py
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/qmanager/acl.py Sat Apr 23 21:02:25 2011 (r220976)
@@ -0,0 +1,156 @@
+# Validate a (uid, (gids)) tuple against an ACL.
+
+import pwd, grp
+
+def getuidbyname(username):
+ if str(username).isdigit():
+ return int(username)
+ return pwd.getpwnam(username)[2]
+
+def getgidbyname(grname):
+ if str(grname).isdigit():
+ return int(grname)
+ return grp.getgrnam(grname)[2]
+
+class ACLElement(object):
+ """ Component of an ACL. """
+
+ def __init__(self, name, uidlist, gidlist, sense):
+ self.name = name
+ self.uidlist = [getuidbyname(uid) for uid in uidlist]
+ self.gidlist = [getgidbyname(gid) for gid in gidlist]
+ self.sense = bool(sense)
+
+ def validate(self, uid, gids):
+ """ Validate an ACL Element. In order to match, the following must
+ hold:
+
+ * uid is a subset of self.uidlist, or self.uidlist is empty
+ * one of the gids must be present in self.gidlist, or
+ self.gidlist is empty
+
+ If both conditions hold, then the validation returns self.sense
+
+ Returns: True/False if Element matches
+ None if Element fails to match
+ """
+
+ if (len(self.uidlist) == 0 or uid in self.uidlist) and \
+ (len(self.gidlist) == 0 or set(gids).intersection(self.gidlist)):
+ return self.sense
+ return None
+
+class ACL(object):
+ """ List of ACLElements that form an ACL """
+
+ def __init__(self, acllist):
+ self.acls = acllist
+
+ def validate(self, uid, gids):
+ uid=getuidbyname(uid)
+ gids=set(getgidbyname(gid) for gid in gids)
+
+ for acl in self.acls:
+ res=acl.validate(uid, gids)
+ if res is not None:
+ return res
+ return False
+
+if __name__ == "__main__":
+
+ from sys import exit
+
+ assert getuidbyname(123) == 123
+ assert getuidbyname('123') == 123
+
+ try:
+ ACLElement("test", ["foobar"], [""], True)
+ except KeyError:
+ pass
+
+ try:
+ ACLElement("test", [123, "foobar"], [""], True)
+ except KeyError:
+ pass
+
+ assert ACLElement("test", [123], [], True) != None
+ assert ACLElement("test", ["123"], [], True) != None
+
+ acl = ACL([ACLElement("el 1", ["kris"], [], True),
+ ACLElement("el 2", [], ["wheel"], True),
+ ACLElement("el 3", [], [], False)])
+
+ assert acl.validate(getuidbyname('kris'), []) == True
+ assert acl.validate(getuidbyname('simon'), []) == False
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('devel'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('root'), [pwd.getpwnam('root')[3]]) == True
+
+ acl = ACL([ACLElement("el 1", ["kris"], ["distcc"], True),
+ ACLElement("el 2", [], ["wheel"], True),
+ ACLElement("el 3", [], [], False)])
+ assert acl.validate("kris", ["wheel"]) == True
+ assert acl.validate("kris", ["staff"]) == False
+
+ acl = ACL([ACLElement("", ('kris',), (), True),
+ ACLElement("", (), ('wheel', 'devel'), True),
+ ACLElement("", (), (), False)])
+
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('devel'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff')]) == False
+
+ acl = ACL([ACLElement("", ('kris',), (), True),
+ ACLElement("", (), ('devel',), True),
+ ACLElement("", (), ('wheel',), True),
+ ACLElement("", (), (), False)])
+
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('devel'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff')]) == False
+
+ acl = ACL([ACLElement("", ('kris',), (), True),
+ ACLElement("", (), ('devel',), False),
+ ACLElement("", (), ('wheel',), True),
+ ACLElement("", (), (), False)])
+
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('devel'), getgidbyname('wheel')]) == False
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff')]) == False
+
+
+ acl = ACL([ACLElement("", ('kris',), (), True),
+ ACLElement("", (), ('devel',), True),
+ ACLElement("", (), ('wheel',), False),
+ ACLElement("", (), (), False)])
+
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('devel'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff'), getgidbyname('wheel')]) == False
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff')]) == False
+
+
+ acl = ACL([ACLElement("", ('kris',), (), True),
+ ACLElement("", (), ('devel',), True),
+ ACLElement("", (), ('wheel',), False),
+ ACLElement("", (), (), True)])
+
+ assert acl.validate(getuidbyname('simon'), []) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('devel'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff'), getgidbyname('wheel')]) == False
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff')]) == True
+
+ acl = ACL([ACLElement("", ('kris',), (), False),
+ ACLElement("", (), ('devel',), True),
+ ACLElement("", (), ('wheel',), False),
+ ACLElement("", (), (), True)])
+
+ assert acl.validate(getuidbyname('simon'), []) == True
+ assert acl.validate(getuidbyname('kris'), []) == False
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('devel'), getgidbyname('wheel')]) == True
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff'), getgidbyname('wheel')]) == False
+ assert acl.validate(getuidbyname('simon'), [getgidbyname('staff')]) == True
+
+ acl = ACL([ACLElement("", (4206,), set([]), True),
+ ACLElement("", (), set([]), False)])
+
+ assert acl.validate(4206, (4206, 31337)) == True
+ assert acl.validate(4201, (4201, 31337)) == False
Added: projects/portbuild/qmanager/dumpdb.py
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/qmanager/dumpdb.py Sat Apr 23 21:02:25 2011 (r220976)
@@ -0,0 +1,140 @@
+#
+# try doing some SQL reads as a test
+#
+from freebsd_config import *
+
+import os, threading, socket, Queue
+
+from signal import *
+from sys import exc_info
+from itertools import chain
+
+from qmanagerobj import *
+
+CONFIG_DIR="/var/portbuild"
+CONFIG_SUBDIR="conf"
+CONFIG_FILENAME="server.conf"
+
+# pieces of qmanagerobj.startup
+def obj_startup(filename):
+
+ engine = create_engine('sqlite:///' + filename, echo=True)
+ Session = sessionmaker(bind=engine)
+ session = Session()
+
+ Base.metadata.create_all(engine)
+
+ return (engine, session)
+
+
+def show_acl( session ):
+
+ acls = session.query(QManagerACL)
+ acls = acls.order_by('name')
+
+ print
+ print 'starting dump of acl table:'
+ print
+
+ for acl in acls:
+
+ print
+ print "name: %s" % acl.name
+ # list
+ print "uidlist: " + str( acl.uidlist )
+ # list
+ print "gidlist: " + str( acl.gidlist )
+ print "sense: " + str( acl.sense )
+
+
+def show_jobs( session ):
+
+ jobs = session.query(Job)
+ jobs = jobs.order_by('id')
+
+ print
+ print 'starting dump of Job table:'
+ print
+
+ for job in jobs:
+
+ print
+ # job ID
+ print "job id: " + `job.id`
+ # Name of job
+ print "name: " + job.name
+ # priority of request
+ print "priority: " + `job.priority`
+ # job type
+ print "type: " + job.type
+ # uid of job owner
+ print "owner: " + `job.owner`
+ # gids of job owner (tuple)
+ #print str( type( job.gids ) )
+ print "gids: " + str( job.gids )
+ # machines that satisfied initial query (list)
+ #print str( type( job.machines ) )
+ print "machines: " + str( job.machines )
+ # Time job started/blocked (must not be modified when job is
+ # blocked or it will corrupt the heapq)
+ print "startttime: " + `job.starttime`
+ # initial machine description in case we have to revalidate (list)
+ # print str( type( job.mdl ) )
+ print "mdl: " + str( job.mdl )
+ # True --> job is running; False --> job is blocked
+ print "running: " + str( job.running )
+
+
+def show_machines( session ):
+
+ machines = session.query(Machine)
+ machines = machines.order_by('name')
+
+ print
+ print 'starting dump of Machines table:'
+ print
+
+ for machine in machines:
+
+ print
+ print "name: %s" % machine.name
+ # list
+ print "acl: " + str( machine.acl )
+ # boolean
+ print "haszfs: " + str( machine.haszfs )
+ # boolean
+ print "online: " + str( machine.online )
+
+
+def show_machines_for_arch( engine, arch ):
+
+ mdl = ["arch = %s" % arch]
+
+ q = SQL.construct(Machine, mdl)
+ res = engine.execute(Machine.__table__.select(q))
+ result = [SQL.to_dict(Machine, i) for i in res]
+
+ print
+ for machine in result:
+ print "machine for %s : %s " % ( arch, machine[ 'name' ] )
+
+
+# main
+
+if __name__ == '__main__':
+
+ print "acquiring engine and session"
+ config = getConfig( CONFIG_DIR, CONFIG_SUBDIR, CONFIG_FILENAME )
+ QMANAGER_PATH = config.get( 'QMANAGER_PATH' )
+ QMANAGER_DATABASE_FILE = config.get( 'QMANAGER_DATABASE_FILE' )
+ (engine, session) = obj_startup( \
+ os.path.join( QMANAGER_PATH, QMANAGER_DATABASE_FILE ) )
+ print "acquired engine and session"
+ # print "engine = '" + str( engine ) + "', session = '" + str( session ) + "'"
+
+ show_acl( session )
+ show_machines( session )
+ show_jobs( session )
+
+ show_machines_for_arch( engine, 'i386' )
+ show_machines_for_arch( engine, 'amd64' )
Added: projects/portbuild/qmanager/packagebuild
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/qmanager/packagebuild Sat Apr 23 21:02:25 2011 (r220976)
@@ -0,0 +1,649 @@
+#!/usr/bin/env python
+
+# Improved build dispatcher. Invoked on server-side from dopackages.
+
+# We try to build leaf packages (those
+# which can be built immediately without requiring additional
+# dependencies to be built) in the order such that the ones required
+# by the longest dependency chains are built first.
+#
+# This has the effect of favouring deep parts of the package tree and
+# evening out the depth over time, hopefully avoiding the situation
+# where the entire cluster waits for a deep part of the tree to
+# build on a small number of machines
+#
+# We can dynamically respond to changes in build machine availability,
+# since the queue manager will block jobs that cannot be immediately
+# satisfied and will unblock us when a job slot becomes available.
+#
+# When a package build fails, it is requeued with a lower priority
+# such that it will rebuild again as soon as no "phase 1" packages
+# are available to build. This prevents the cluster staying idle
+# until the last phase 1 package builds.
+#
+# Other advantages are that this system is easily customizable and in
+# the future will let us customize things like the matching policy of
+# jobs to machines. For example, we could avoid dispatching multiple
+# openoffice builds to the same system.
+#
+# TODO:
+# * Combine build prep stages?
+# - initial check for file up-to-date
+# * check mtime for package staleness (cf make)
+# * option to skip phase 2
+
+from qmanagerclient import *
+
+from freebsd_config import *
+
+import os, string, sys, threading, time, subprocess
+#import random
+from itertools import chain
+#import gc
+from stat import *
+
+from Queue import Queue
+from heapq import *
+
+CONFIG_DIR="/var/portbuild"
+CONFIG_SUBDIR="conf"
+CONFIG_FILENAME="server.conf"
+
+config = getConfig( CONFIG_DIR, CONFIG_SUBDIR, CONFIG_FILENAME )
+QMANAGER_MAX_JOB_ATTEMPTS = int( \
+ config.get( 'QMANAGER_MAX_JOB_ATTEMPTS' ) )
+QMANAGER_PRIORITY_PACKAGES = string.split( \
+ config.get( 'QMANAGER_PRIORITY_PACKAGES' ) )
+QMANAGER_RUNAWAY_PERCENTAGE = float( \
+ config.get( 'QMANAGER_RUNAWAY_PERCENTAGE' ) )
+QMANAGER_RUNAWAY_THRESHOLD = int( \
+ config.get( 'QMANAGER_RUNAWAY_THRESHOLD' ) )
+
+DEBUG = False
+
+categories = {}
+ports = {}
+
+# When a build fails we requeue it with a lower priority such that it
+# will never preempt a phase 1 build but will build when spare
+# capacity is available.
+PHASE2_BASE_PRIO=1000
+
+# Process success quickly so other jobs are started
+SUCCESS_PRIO = -1000
+
+# Failure should be a less common event :)
+FAILURE_PRIO = -900
+
+# Port status codes
+PENDING = 1 # Yet to build
+PHASE2 = 2 # Failed once
+
+class PriorityQueue(Queue):
+ """Variant of Queue that retrieves open entries in
+ priority order (lowest first).
+ Entries are typically tuples of the form: (priority number,
+ data)
+ This class can be found at: Python-2.6a3/Lib/Queue.py
+ """
+ maxsize = 0
+
+ def _init(self, maxsize):
+ self.queue = []
+
+ def _qsize(self, len=len):
+ return len(self.queue)
+
+ def _put(self, item, heappush=heappush):
+ heappush(self.queue, item)
+
+ def _get(self, heappop=heappop):
+ return heappop(self.queue)
+
+class Index(object):
+
+ def __init__(self, indexfile):
+ self.indexfile = indexfile
+
+ def parse(self, targets = None):
+
+ print "[MASTER] Read index"
+ f = file(self.indexfile)
+ index = f.readlines()
+ f.close()
+ f = None
+ del f
+
+ lines=[]
+ print "[MASTER] Phase 1"
+ for i in index:
+ (name, path, prefix, comment, descr, maintainer, categories, bdep,
+ rdep, www, edep, pdep, fdep) = i.rstrip().split("|")
+
+ if targets is None or name in targets:
+ lines.append((name, bdep, rdep, edep, pdep, fdep))
+
+ Port(name, path, "", "", "", "",
+ categories, "")
+ index = None
+ del index
+
+ print "[MASTER] Phase 2"
+ for (name, bdep, rdep, edep, pdep, fdep) in lines:
+ ports[name].setdeps(bdep, rdep, edep, pdep, fdep)
+
+ lines = None
+ del lines
+ print "[MASTER] Done"
+
+def depthindex(targets):
+ """ Initial population of depth tree """
+
+ for i in targets:
+ i.depth_recursive()
+
+class Port(object):
+
+ def __init__(self, name, path, prefix, comment, descr, maintainer,
+ cats, www):
+
+ __slots__ = ["name", "path", "prefix", "comment", "descr",
+ "maintainer", "www", "bdep", "rdep", "edep", "pdep",
+ "fdep", "alldep", "parents", "depth", "categories"]
+
+ self.name = name
+ self.path = path
+ self.prefix = prefix
+ self.comment = comment
+ self.descr = descr
+ self.maintainer = maintainer
+ self.www = www
+
+ # Populated later
+ self.bdep = []
+ self.rdep = []
+ self.edep = []
+ self.pdep = []
+ self.fdep = []
+
+ self.alldep = []
+ self.parents = []
+ self.id = None # XXX
+
+ self.status = PENDING
+ self.attempts = 0
+
+ # Whether the package build has completed and is hanging around
+ # to resolve dependencies for others XXX use status
+ self.done = False
+
+ # Depth is the maximum length of the dependency chain of this port
+ self.depth = None
+
+ self.categories=[]
+ scats = cats.split()
+ if len(scats) != len(set(scats)):
+ print "[MASTER] Warning: port %s includes duplicated categories: %s" % (name, cats)
+
+ for c in set(scats):
+ try:
+ cat = categories[c]
+ except KeyError:
+ cat = Category(c)
+
+ self.categories.append(cat)
+ cat.add(self)
+
+ ports[name] = self
+
+ def remove(self):
+ """ Clean ourselves up but don't touch references in other objects;
+they still need to know about us as dependencies etc """
+
+ self.fdep = None
+ self.edep = None
+ self.pdep = None
+ self.bdep = None
+ self.rdep = None
+ self.alldep = None
+ self.parents = None
+
+ for cat in self.categories:
+ cat.remove(self)
+
+ ports[self.name] = None
+ del ports[self.name]
+ del self
+
+ def destroy(self):
+ """ Remove a package and all references to it """
+
+ for pkg in self.alldep:
+ if pkg.parents is not None:
+ # Already removed but not destroyed
+ try:
+ pkg.parents.remove(self)
+ except ValueError:
+ continue
+
+ for pkg in self.parents:
+ try:
+ pkg.fdep.remove(self)
+ except ValueError:
+ pass
+ try:
+ pkg.edep.remove(self)
+ except ValueError:
+ pass
+ try:
+ pkg.pdep.remove(self)
+ except ValueError:
+ pass
+ try:
+ pkg.bdep.remove(self)
+ except ValueError:
+ pass
+ try:
+ pkg.rdep.remove(self)
+ except ValueError:
+ pass
+ pkg.alldep.remove(self)
+
+ sys.exc_clear()
+
+ self.remove()
+
+ def setdeps(self, bdep, rdep, edep, pdep, fdep):
+ self.fdep = [ports[p] for p in fdep.split()]
+ self.edep = [ports[p] for p in edep.split()]
+ self.pdep = [ports[p] for p in pdep.split()]
+ self.bdep = [ports[p] for p in bdep.split()]
+ self.rdep = [ports[p] for p in rdep.split()]
+
+ self.alldep = list(set(chain(self.fdep, self.edep, self.pdep,
+ self.bdep, self.rdep)))
+
+ for p in self.alldep:
+ p.parents.append(self)
+
+ def depth_recursive(self):
+
+ """
+ Recursively populate the depth tree up from a given package
+ through dependencies, assuming empty values on entries not yet
+ visited
+ """
+
+ if self.depth is None:
+ if len(self.parents) > 0:
+ max = 0
+ for i in self.parents:
+ w = i.depth_recursive()
+ if w > max:
+ max = w
+ self.depth = max + 1
+ else:
+ self.depth = 1
+ for port in QMANAGER_PRIORITY_PACKAGES:
+ if self.name.startswith(port):
+ # Artificial boost to try and get it building earlier
+ self.depth = 100
+ return self.depth
+
+ def destroy_recursive(self):
+ """ Remove a port and everything that depends on it """
+
+ parents=set([self])
+
+ while len(parents) > 0:
+ pkg = parents.pop()
+ assert pkg.depth is not None
+ parents.update(pkg.parents)
+ pkg.destroy()
+
+ def success(self):
+ """ Build succeeded and possibly uncovered some new leaves """
+
+ parents = self.parents[:]
+ self.done = True
+ self.remove()
+
+ newleafs = [p for p in parents if all(c.done for c in p.alldep)]
+ return newleafs
+
+ def failure(self):
+ """ Build failed """
+
+ self.destroy_recursive()
+
+ def packagename(self, arch, branch, buildid):
+ """ Return the path where a package may be found"""
+
+ return "/var/portbuild/%s/%s/builds/%s/packages/All/%s.tbz" \
+ % (arch, branch, buildid, self.name)
+
+ def is_stale(self, arch, branch, buildid):
+ """ Does a package need to be (re)-built?
+
+ Returns: False: if it exists and has newer mtime than all of
+ its dependencies.
+ True: otherwise
+ """
+
+ my_pkgname = self.packagename(arch, branch, buildid)
+ pkg_exists = os.path.exists(my_pkgname)
+
+ if pkg_exists:
+ my_mtime = os.stat(my_pkgname)[ST_MTIME]
+
+ dep_packages = [pkg.packagename(arch, branch, buildid)
+ for pkg in self.alldep]
+ deps_exist = all(os.path.exists(pkg) for pkg in dep_packages)
+ return not (pkg_exists and deps_exist and
+ all(os.stat(pkg)[ST_MTIME] <= my_mtime
+ for pkg in dep_packages))
+
+class Category(object):
+ def __init__(self, name):
+ self.name = name
+ self.ports = {}
+ categories[name] = self
+
+ def add(self, port):
+ self.ports[port] = port
+
+ def remove(self, port):
+ self.ports[port]=None
+ del self.ports[port]
+
+def gettargets(targets):
+ """ split command line arguments into list of packages to build.
+ Returns set or iterable of all ports that will be built including
+ dependencies """
+
+ plist = set()
+ if len(targets) == 0:
+ targets = ["all"]
+ for i in targets:
+ if i == "all":
+ return ports.itervalues()
+
+ if i.endswith("-all"):
+ cat = i.rpartition("-")[0]
+ plist.update(p.name for p in categories[cat].ports)
+ elif i.rstrip(".tbz") in ports:
+ plist.update([ports[i.rstrip(".tbz")].name])
+ else:
+ raise KeyError, i
+
+ # Compute transitive closure of all dependencies
+ pleft=plist.copy()
+ while len(pleft) > 0:
+ pkg = pleft.pop()
+ new = [p.name for p in ports[pkg].alldep]
+ plist.update(new)
+ pleft.update(new)
+
+ for p in set(ports.keys()).difference(plist):
+ ports[p].destroy()
+
+ return [ports[p] for p in plist]
+
+class worker(threading.Thread):
+
+ # Protects threads
+ lock = threading.Lock()
+
+ # Running threads, used for collecting status
+ threads = {}
+
+ def __init__(self, mach, job, arch, branch, buildid, queue):
+ threading.Thread.__init__(self)
+ self.machine = mach
+ self.job = job
+ self.arch = arch
+ self.branch = branch
+ self.buildid = buildid
+ self.queue = queue
+
+ self.setDaemon(True)
+
+ def run(self):
+ pkg = self.job
+
+ print "[MASTER] Running job %s" % (pkg.name),
+ if pkg.status == PHASE2:
+ print " (phase 2)"
+ else:
+ print
+ try:
+ runenv={'HOME':"/root",
+ 'PATH':'/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/var/portbuild/scripts',
+ 'FD':" ".join(["%s.tbz" % p.name for p in pkg.fdep]),
+ 'ED':" ".join(["%s.tbz" % p.name for p in pkg.edep]),
+ 'PD':" ".join(["%s.tbz" % p.name for p in pkg.pdep]),
+ 'BD':" ".join(["%s.tbz" % p.name for p in pkg.bdep]),
+ 'RD':" ".join(["%s.tbz" % p.name for p in pkg.rdep])}
+ for var in ["NOCLEAN", "NO_RESTRICTED", "NOPLISTCHECK", "NO_DISTFILES", "FETCH_ORIGINAL", "TRYBROKEN" ]:
+ if var in os.environ:
+ runenv[var] = os.environ.get(var)
+ build = subprocess.Popen(
+ ["/bin/sh", "/var/portbuild/scripts/pdispatch",
+ self.arch, self.branch, self.buildid, self.machine,
+ "/var/portbuild/scripts/portbuild", "%s.tbz" % pkg.name,
+ pkg.path],
+ env=runenv,
+ stderr=subprocess.STDOUT, stdout=subprocess.PIPE, bufsize=0)
+ except OSError, e:
+ print >>sys.stderr, "[%s:%s]: Execution failed: %s" % \
+ (pkg.id, pkg.name, e)
+ while True:
+ try:
+ line = build.stdout.readline()
+ except:
+ print "[%s:%s]: Failed reading from build script" % \
+ (pkg.id, pkg.name)
+ break
+ if line == "":
+ break
+ print "[%s:%s] %s" % (pkg.id, pkg.name, line.rstrip())
+
+ retcode = build.wait()
+
+# time.sleep(random.randint(0,60))
+#
+# r = random.random()
+# if r < 0.1:
+# retcode = 1
+# elif r < 0.15:
+# retcode = 254
+# else:
+# retcode = 0
+
+ conn = QManagerClientConn(stderr = sys.stderr)
+ timeout = 1
+ try:
+ (code, vars) = conn.command("release", {'id':pkg.id})
+ except RequestError, e:
+ print "[MASTER] Error releasing job %s (%s): %s" % (pkg.name, pkg.id, e.value)
+
+ if DEBUG:
+ print "[MASTER] got retcode %d from pkg %s" % (retcode, pkg.name)
+ if retcode == 254:
+ # Requeue soft failure at original priority
+ # XXX exponential backoff?
+ time.sleep(60)
+# print "Requeueing %s" % pkg.id
+ self.queue.put((-pkg.depth, pkg))
+ elif retcode == 253:
+ # setting up a machine, we should immediately retry
+ self.queue.put((-pkg.depth, pkg))
+ elif retcode == 0:
+ self.queue.put((SUCCESS_PRIO, pkg))
+ else:
+ self.queue.put((FAILURE_PRIO, pkg))
+
+ # Clean up
+ worker.lock.acquire()
+ worker.threads[self]=None
+ del worker.threads[self]
+ worker.lock.release()
+
+ @staticmethod
+ def dispatch(mach, job, arch, branch, buildid, queue):
+ wrk = worker(mach, job, arch, branch, buildid, queue)
+
+ worker.lock.acquire()
+ worker.threads[wrk] = wrk
+ worker.lock.release()
+
+ wrk.start()
+
+def main(arch, branch, buildid, args):
+ global index
+
+ basedir="/var/portbuild/"+arch+"/"+branch+"/builds/"+buildid
+ portsdir=basedir+"/ports"
+
+ # get the major branch number.
+ branchbase = branch.split("-")[ 0 ]
+ # XXX ERWLA - Ugly hack
+ branchbase = branchbase.split(".")[ 0 ]
+ indexfile=portsdir+"/INDEX-"+branchbase
+
+ print "[MASTER] parseindex..."
+ index = Index(indexfile)
+ index.parse()
+ print "[MASTER] length = %s" % len(ports)
+
+ print "[MASTER] Finding targets..."
+ targets = gettargets(args)
+
+ print "[MASTER] Calculating depth..."
+ depthindex(targets)
+
+ print "[MASTER] Pruning duds..."
+ dudsfile=basedir+"/duds"
+ for line in file(dudsfile):
+ try:
+ dud = ports[line.rstrip()]
+ except KeyError:
+ continue
+ print "[MASTER] Skipping %s (duds)" % dud.name
+ dud.destroy_recursive()
+
+ queue = PriorityQueue()
+ # XXX can do this while parsing index if we prune targets/duds
+ # first
+ for pkg in ports.itervalues():
+ if len(pkg.alldep) == 0:
+ queue.put((-pkg.depth, pkg))
+
+ # XXX check osversion, pool
+ mdl=["arch = %s" % arch]
+
+ # Main work loop
+ completed_jobs = 0
+ failed_jobs = 0
+ while len(ports) > 0:
+ print "[MASTER] Ports remaining=%s, Queue length=%s" % (len(ports), queue.qsize())
+
+ if len(ports) < 10:
+ print "[MASTER] Remaining ports: %s" % ports.keys()
+
+ (prio, job) = queue.get()
+ if DEBUG:
+ print "[MASTER] Job %s pulled from queue with prio %d" % ( job.name, prio )
+ if prio == SUCCESS_PRIO:
+ print "[MASTER] Job %s succeeded" % job.name
+ for new in job.success():
+ queue.put((-new.depth, new))
+ completed_jobs = completed_jobs + 1
+ continue
+ elif prio == FAILURE_PRIO:
+ if job.status == PHASE2:
+ print "[MASTER] Job %s failed" % job.name
+ job.failure()
+ continue
+ else:
+ # XXX MCL 20110421
+ completed_jobs = completed_jobs + 1
+ failed_jobs = failed_jobs + 1
+ if DEBUG:
+ print "[MASTER] jobs: %d failed jobs out of %d:" % \
+ ( failed_jobs, completed_jobs )
+ if completed_jobs > QMANAGER_RUNAWAY_THRESHOLD and \
+ float( failed_jobs ) / completed_jobs > QMANAGER_RUNAWAY_PERCENTAGE:
+ print "[MASTER] ERROR: runaway build detected: %d failed jobs out of %d:" % \
+ ( failed_jobs, completed_jobs )
+ print "[MASTER] RUN TERMINATED."
+ break
+
+ job.attempts = job.attempts + 1
+ # XXX MCL in theory, if all this code worked correctly,
+ # this condition would never trigger. In practice,
+ # however, it does, so bomb out before filling portmgr's
+ # mbox.
+ # XXX MCL 20110422 perhaps this code has been fixed now;
+ # XXX it did not use to work:
+ if job.attempts > QMANAGER_MAX_JOB_ATTEMPTS:
+ print "[MASTER] Job %s failed %d times; RUN TERMINATED." % ( job.name, job.attempts )
+ break
+ else:
+ # Requeue at low priority
+ print "[MASTER] Job %s failed (requeued for phase 2)" % job.name
+ job.status = PHASE2
+ queue.put((PHASE2_BASE_PRIO-job.depth, job))
+ continue
+ elif job.status == PHASE2:
+ depth = -(prio - PHASE2_BASE_PRIO)
+ else:
+ depth = -prio
+
+ print "[MASTER] Working on job %s, depth %d" % (job.name, depth)
+ if job.is_stale(arch, branch, buildid):
+ conn = QManagerClientConn(stderr = sys.stderr)
+ (code, vars) = conn.command("acquire",
+ {"name":job.name,
+ "type":"%s/%s/%s package" % \
+ (arch, branch, buildid),
+ "priority":10, "mdl":mdl})
+
+ if code[0] == "2":
+ machine=vars['machine']
+ job.id=vars['id']
+# print "Got ID %s" % job.id
+
+ worker.dispatch(machine, job, arch, branch, buildid, queue)
+ else:
+ print "[MASTER] Error acquiring job %s: %s" % (pkg.name, code)
+ else:
+ print "[MASTER] Skipping %s since it already exists" % job.name
+ for new in job.success():
+ queue.put((-new.depth, new))
+
+ print "[MASTER] Waiting for threads"
+ threads = worker.threads.copy()
+
+ for t in threads:
+ print "[MASTER] Outstanding thread: %s" % t.job.name
+
+ for t in threads:
+ print "[MASTER] Waiting for thread %s" % t.job.name
+ t.join()
+
+ print "[MASTER] Finished"
+
+if __name__ == "__main__":
+
+ try:
+ main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4:])
+ sys.exit( 0 )
+ except Exception, e:
+ # XXX MCL TODO move this above
+ print "packagebuild: Exception:"
+ try:
+ print str( e )
+ except:
+ pass
+ sys.exit( 1 )
Added: projects/portbuild/qmanager/qclient
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/portbuild/qmanager/qclient Sat Apr 23 21:02:25 2011 (r220976)
@@ -0,0 +1,242 @@
+#!/usr/bin/env python
+
+# queue manager client
+
+# TODO:
+# * pretty-print command output
+
+import socket, os, sys
+
+from optparse import OptionParser
+from qmanagerclient import *
+
+def error(msg):
+ print >>sys.stderr, "%s: %s" % (sys.argv[0], msg.rstrip())
+ sys.exit(1)
+
+def buildquery(option, opt, values, parser):
+ """
+ Turn command line options into a query description
+
+ Modifies:
+ query global
+
+ Raises:
+ ValueError if bogus arguments to numeric operators
+
+ """
+ global query
+
+ numopt = False
+ if opt in ("-m", "--machine"):
+ key="name"
+
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***