import plugins
import repository
import transaction
+import util
from constants import *
from errors import BuildError, PakfireError
# Check if we are operating as the root user.
self.check_root_user()
+ # Generate a random value.
+ rnd = random.sample(string.lowercase + string.digits, 12)
+ rnd = "".join(rnd)
+
# The path where we are operating in
self.path = path
+ self.tempdir = os.path.join(LOCAL_TMP_PATH, rnd)
+
+ if not os.path.exists(self.tempdir):
+ os.makedirs(self.tempdir)
# Save if we are in the builder mode
self.builder = builder
if self.builder:
- rnd = random.sample(string.lowercase + string.digits, 12)
- self.path = os.path.join(BUILD_ROOT, "".join(rnd))
+ self.path = os.path.join(BUILD_ROOT, rnd)
self.debug = False
# always work with valid data.
self.repos.update()
+ def __del__(self):
+ util.rm(self.tempdir)
+
+ @property
+ def supported_arches(self):
+ return self.distro.supported_arches
+
def check_root_user(self):
if not os.getuid() == 0 or not os.getgid() == 0:
raise Exception, "You must run pakfire as the root user."
raise BuildError, arch
- def build(self, pkg, arch=None, resultdirs=None):
+ def build(self, pkg, arch=None, resultdirs=None, **kwargs):
self.check_build_mode()
self.check_host_arch(arch)
# Always include local repository
resultdirs.append(self.repos.local_build.path)
- b = builder.Builder(pakfire=self, pkg=pkg)
+ b = builder.Builder(pakfire=self, pkg=pkg, **kwargs)
try:
b.prepare()
# Add sub-commands.
self.sub_commands = self.parser.add_subparsers()
+ self.parse_command_build()
self.parse_command_keepalive()
# Finally parse all arguments from the command line and save them.
self.slave = server.slave.Slave(self.pakfire)
self.action2func = {
+ "build" : self.handle_build,
"keepalive" : self.handle_keepalive,
}
+ def parse_command_build(self):
+ # Implement the "build" command.
+ sub_keepalive = self.sub_commands.add_parser("build",
+ help=_("Request a build job from the server."))
+ sub_keepalive.add_argument("action", action="store_const", const="build")
+
def parse_command_keepalive(self):
# Implement the "keepalive" command.
sub_keepalive = self.sub_commands.add_parser("keepalive",
def handle_keepalive(self):
self.slave.keepalive()
+ def handle_build(self):
+ self.slave.build_job()
REPO_CACHE_DIR = os.path.join(CACHE_DIR, "repos")
LOCAL_BUILD_REPO_PATH = "/var/lib/pakfire/local"
+LOCAL_TMP_PATH = "/var/tmp/pakfire"
PACKAGES_DB_DIR = "var/lib/pakfire"
PACKAGES_DB = os.path.join(PACKAGES_DB_DIR, "packages.db")
if not revision:
revision = self.revision
- revs = self._git("rev-list %s..origin/%s --no-merges" % (revision, self.branch))
+ command = "rev-list %s..origin/%s" % (revision, self.branch)
- return reversed(revs.splitlines())
+ # Get all normal commits.
+ commits = self._git("%s --no-merges" % command)
+ commits = commits.splitlines()
+
+ revisions = []
+ for commit in self._git(command).splitlines():
+ # Check if commit is a normal commit or merge commit.
+ merge = not commit in commits
+
+ revisions.append((commit, merge))
+
+ return reversed(revisions)
def _git_changed_files(self, revision1, revision2=""):
files = self._git("diff --name-only %s %s" % (revision1, revision2))
def _git_checkout_revision(self, revision):
self._git("checkout %s" % revision)
- def update_revision(self, revision):
- self._git_checkout_revision(revision)
+ def update_revision(self, (revision, merge)):
+ if not merge:
+ self._git_checkout_revision(revision)
- # Get list of all changes files between the current revision and
- # the previous one.
- files = self._git_changed_files("HEAD^", "HEAD")
+ # Get list of all changes files between the current revision and
+ # the previous one.
+ files = self._git_changed_files("HEAD^", "HEAD")
- self.update_files([f for f in files if f.endswith(".%s" % MAKEFILE_EXTENSION)])
+ self.update_files([f for f in files if f.endswith(".%s" % MAKEFILE_EXTENSION)])
# Send update to the server.
- self.master.update_revision(self, revision)
+ self.master.update_revision(self, revision)
def update_files(self, files):
rnd = random.randint(0, 1024**2)
import socket
import xmlrpclib
+import pakfire.downloader
+import pakfire.packages
+
+from pakfire.errors import *
+
class Slave(object):
def __init__(self, pakfire):
self.pakfire = pakfire
self.conn = xmlrpclib.Server(server)
+ @property
+ def hostname(self):
+ """
+ Return the host's name.
+ """
+ return socket.gethostname()
+
def keepalive(self):
"""
Send the server a keep-alive to say that we are still there.
"""
- hostname = socket.gethostname()
+ hostname = self.hostname
l1, l5, l15 = os.getloadavg()
logging.info("Sending the server a keepalive: %s" % hostname)
- self.conn.keepalive(hostname, l5)
+ # Get all supported architectures and send them to the server.
+ arches = [a for a in self.pakfire.supported_arches]
+ arches.sort()
+
+ self.conn.keepalive(hostname, l5, arches)
+
+ def update_build_status(self, build_id, status, message=""):
+ self.conn.update_build_state(build_id, status, message)
+
+ def build_job(self):
+ build = self.conn.build_job(self.hostname)
+
+ # If the server has got no job for us, we end right here.
+ if not build:
+ return
+
+ build_id = build["id"]
+ filename = build["source"]
+
+ # Get a package grabber and add mirror download capabilities to it.
+ grabber = pakfire.downloader.PackageDownloader()
+
+ # Temporary path to store the source.
+ tempfile = os.path.join(self.pakfire.tempdir, os.path.basename(filename))
+
+ # Download the source.
+ grabber.urlgrab(filename, filename=tempfile)
+
+ # Read the package file.
+ pkg = pakfire.packages.SourcePackage(self.pakfire,
+ self.pakfire.repos.dummy, tempfile)
+
+ try:
+ self.update_build_status(build_id, "running")
+
+ self.pakfire.build(pkg, build_id=build_id)
+
+ except DependencyError, e:
+ self.update_build_status(build_id, "dependency_error", e)
+
+ except:
+ self.update_build_status(build_id, "failed")
+
+ self.update_build_status(build_id, "finished")