Check in mobile buildbot configs. Copying perfrunner.py so as not to affect production talos, even though I'm just adding two new classes. I'll merge into buildbotcustom once bug 448047 is fixed. Bug 471599, r=alice
authorAki Sasaki <asasaki@mozilla.com>
Fri, 01 May 2009 15:17:45 -0700
changeset 1127 7cb377ca0adac93a822c173187fff863ae2506a4
parent 1126 aea0a3374887c98ac606088701b2955ab960a742
child 1128 fc736b372ce8cb783f2f32a82183a06bc52e1511
push id1
push userroot
push dateWed, 17 Dec 2014 00:18:48 +0000
reviewersalice
bugs448047, 471599
Check in mobile buildbot configs. Copying perfrunner.py so as not to affect production talos, even though I'm just adding two new classes. I'll merge into buildbotcustom once bug 448047 is fixed. Bug 471599, r=alice
mobile-staging/master.cfg
mobile-staging/perfrunner.py
mobile/master.cfg
mobile/perfrunner.py
new file mode 100644
--- /dev/null
+++ b/mobile-staging/master.cfg
@@ -0,0 +1,186 @@
+###########################################################################
+# mobile-staging master.cfg
+# Built largely from perf-staging/master.cfg, but will most likely also
+# contain unit tests.
+###########################################################################
+
+import os.path
+import re
+
+from buildbot.buildslave import BuildSlave
+
+from buildbot.process.factory import BuildFactory
+from buildbot.scheduler import Scheduler
+from buildbot.status import html, tinderbox
+from buildbot.status.mail import MailNotifier
+from tinderboxmailnotifier import TinderboxMailNotifier
+from buildbot.steps.shell import Compile, ShellCommand, WithProperties
+from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE, SKIPPED, EXCEPTION
+
+import perfrunner
+reload(perfrunner)
+from perfrunner import *
+
+import ftppoller
+reload(ftppoller)
+from ftppoller import FtpPoller
+
+
+MAEMO_SEARCHSTRING="en-US.linux-arm.tar.bz2"
+MAEMO_TRUNK_BUILDDIRS = [
+    "http://ftp.mozilla.org/pub/mozilla.org/firefox/tinderbox-builds/mobile-browser-linux-arm/",
+    "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mobile-browser/",
+    "http://10.250.3.10/maemo/"
+]
+
+TINDERBOX_TREE="MozillaTest"
+RESULTS_SERVER="graphs-stage.mozilla.org"
+
+c = BuildmasterConfig = {}
+
+##
+## Misc Config
+##
+
+c['debugPassword'] = "mozilla"
+c['projectName'] = "Talos"
+c['projectURL'] = "http://quality.mozilla.org/en/projects/automation/talos"
+c['buildbotURL'] = "http://staging-mobile-master.mozilla.org:8011"
+c['slavePortnum'] = 9011
+
+
+##
+## Slaves
+##
+
+c['slaves'] = [
+               BuildSlave("maemo-n810-01", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-02", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-03", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-04", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-05", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-06", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-07", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-08", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-09", "m0b1l3", max_builds=1),
+              ]
+
+##
+## Status
+##
+
+c['status'] = []
+c['status'].append(html.WebStatus(http_port=8011, allowForce=True))
+
+c['status'].append(MailNotifier(
+    fromaddr="talos.buildbot@build.mozilla.org",
+    sendToInterestedUsers=False,
+    extraRecipients=['aki@mozilla.com'],
+    mode="failing",
+    builders=None,
+    relayhost="smtp.mozilla.org"
+))
+
+c['status'].append(tinderbox.TinderboxMailNotifier(
+    fromaddr="talos.buildbot@build.mozilla.org",
+    tree=TINDERBOX_TREE,
+    extraRecipients=["tinderbox-daemon@tinderbox.mozilla.org"],
+    relayhost="smtp.mozilla.org",
+    builders=["N810 Talos Tp", "N810 Talos non-Tp", "N810 Talos Tp JIT"],
+    logCompression="bzip2"
+))
+
+
+##
+## Sources
+##
+
+c['change_source'] = []
+
+c['change_source'].append(FtpPoller(
+    tree = "mobile",
+    branch = "mobile-browser-maemo",
+    pollInterval = 1 * 60,
+    ftpURLs = MAEMO_TRUNK_BUILDDIRS,
+    searchString = MAEMO_SEARCHSTRING
+))
+
+
+##
+## Schedulers
+##
+
+c['schedulers'] = []
+
+c['schedulers'].append(Scheduler(
+    name="maemo scheduler",
+    branch="mobile-browser-maemo",
+    treeStableTimer=1*60,
+    builderNames=[
+        'N810 Talos Tp',
+        'N810 Talos non-Tp',
+        'N810 Talos Tp JIT',
+    ]
+))
+
+maemoTalosStepsTp = MaemoTalosFactory(
+    activeTests={
+        'tp':     90,
+    },
+    talosConfigFile='mobile.config',
+    resultsServer=RESULTS_SERVER,
+    branch='mobile-browser',
+    hackTbPrint=1,
+)
+
+maemoTalosStepsTpJIT = MaemoTalosFactory(
+    activeTests={
+        'tp':     90,
+    },
+    disableJit=0,
+    talosConfigFile='mobile.config',
+    resultsServer=RESULTS_SERVER,
+    branch='mobile-browser',
+    hackTbPrint=1,
+)
+
+maemoTalosStepsNonTp = MaemoTalosFactory(
+    activeTests={
+        'ts':     60,
+        'tdhtml': 60,
+        'tsvg':   60,
+        'twinopen':   60,
+        'tsspider':   60,
+        'tgfx':   60,
+    },
+    talosConfigFile='mobile.config',
+    resultsServer=RESULTS_SERVER,
+    branch='mobile-browser',
+    hackTbPrint=1,
+)
+
+n810_trunk_tp = {
+    'name': "N810 Talos Tp",
+    'slavenames': ['maemo-n810-01', 'maemo-n810-02', 'maemo-n810-03'],
+    'builddir': "n810-trunk-tp",
+    'factory': maemoTalosStepsTp,
+    'category': "Mobile"
+}
+
+n810_trunk_non_tp = {
+    'name': "N810 Talos non-Tp",
+    'slavenames': ['maemo-n810-04', 'maemo-n810-05', 'maemo-n810-06', 'maemo-n810-07', 'maemo-n810-08', 'maemo-n810-09'],
+    'builddir': "n810-trunk-non-tp",
+    'factory': maemoTalosStepsNonTp,
+    'category': "Mobile"
+}
+
+n810_trunk_tp_jit = {
+    'name': "N810 Talos Tp JIT",
+    'slavenames': ['maemo-n810-07', 'maemo-n810-08', 'maemo-n810-09'],
+    'builddir': "n810-trunk-tp-jit",
+    'factory': maemoTalosStepsTpJIT,
+    'category': "Mobile"
+}
+
+c['builders'] = [n810_trunk_tp, n810_trunk_non_tp, n810_trunk_tp_jit]
new file mode 100644
--- /dev/null
+++ b/mobile-staging/perfrunner.py
@@ -0,0 +1,714 @@
+# -*- Python -*-
+
+from twisted.python import log
+from buildbot import buildset
+from buildbot.scheduler import Scheduler
+from buildbot.process.buildstep import BuildStep
+from buildbot.process.factory import BuildFactory
+from buildbot.buildset import BuildSet
+from buildbot.sourcestamp import SourceStamp
+from buildbot.steps.shell import ShellCommand, WithProperties
+from buildbot.steps.transfer import FileDownload
+from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE, SKIPPED, EXCEPTION
+import re, urllib, sys, os
+from time import strptime, strftime, localtime
+from datetime import datetime
+from os import path
+import copy
+
+MozillaEnvironments = { }
+
+# platform SDK location.  we can build both from one generic template.
+# modified from vc8 environment
+MozillaEnvironments['vc8perf'] = {
+    "MOZ_CRASHREPORTER_NO_REPORT": '1',
+    "MOZ_NO_REMOTE": '1',
+    "NO_EM_RESTART": '1',
+    "XPCOM_DEBUG_BREAK": 'warn',
+    "CYGWINBASE": 'C:\\cygwin',
+    "PATH": 'C:\\Python24;' + \
+            'C:\\Python24\\Scripts;' + \
+            'C:\\cygwin\\bin;' + \
+            'C:\\WINDOWS\\System32;' + \
+            'C:\\program files\\gnuwin32\\bin;' + \
+            'C:\\WINDOWS;'
+}
+
+MozillaEnvironments['linux'] = {
+    "MOZ_CRASHREPORTER_NO_REPORT": '1',
+    "MOZ_NO_REMOTE": '1',
+    "NO_EM_RESTART": '1',
+    "XPCOM_DEBUG_BREAK": 'warn',
+    "DISPLAY": ":0",
+}
+
+MozillaEnvironments['mac'] = {
+    "MOZ_NO_REMOTE": '1',
+    "NO_EM_RESTART": '1',
+    "XPCOM_DEBUG_BREAK": 'warn',
+    "MOZ_CRASHREPORTER_NO_REPORT": '1',
+    # for extracting dmg's
+    "PAGER": '/bin/cat',
+}
+
+class MultiBuildScheduler(Scheduler):
+    """Trigger N (default three) build requests based upon the same change request"""
+    def __init__(self, numberOfBuildsToTrigger=3, **kwargs):
+        self.numberOfBuildsToTrigger = numberOfBuildsToTrigger
+        Scheduler.__init__(self, **kwargs)
+
+    def fireTimer(self):
+        self.timer = None
+        self.nextBuildTime = None
+        changes = self.importantChanges + self.unimportantChanges
+        self.importantChanges = []
+        self.unimportantChanges = []
+
+        # submit
+        for i in range(0, self.numberOfBuildsToTrigger):
+            bs = buildset.BuildSet(self.builderNames, SourceStamp(changes=changes))
+            self.submitBuildSet(bs)
+
+
+class MozillaWget(ShellCommand):
+    """Download built Firefox client from dated staging directory."""
+    haltOnFailure = True
+    
+    def __init__(self, branch="HEAD", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(branch=branch, command=command)
+        self.branch = branch
+        self.command = command or ["wget"]
+
+    def setBuild(self, build):
+        ShellCommand.setBuild(self, build)
+        self.changes = build.source.changes
+        #a full url is always provided by sendchange
+        self.fileURL = self.changes[-1].files[0]
+        self.filename = os.path.basename(self.fileURL)
+        # Lie about when we started so the talos runs line up with builds on
+        # the waterfall
+        try:
+            timestamp = int(os.path.basename(os.path.dirname(self.fileURL)))
+            self.changes[-1].when = timestamp
+        except:
+            pass
+    
+    def getFilename(self):
+        return self.filename
+    
+    def describe(self, done=False):
+        return ["Wget Download"]
+    
+    def start(self):
+        if self.branch:
+            self.setProperty("fileURL", self.fileURL)
+            self.setProperty("filename", self.filename)
+        self.setCommand(["wget", "-nv", "-N", self.fileURL])
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        if None != re.search('ERROR', cmd.logs['stdio'].getText()):
+            return FAILURE
+        return SUCCESS
+
+
+class MozillaWgetSymbols(ShellCommand):
+    """Download the matching symbol package with a build."""
+    haltOnFailure = False
+    _suffixes = ('.tar.bz2', '.dmg', '.zip')
+
+    def __init__(self, **kwargs):
+        #def setBuild(self, build):
+        #    ShellCommand.setBuild(self, build)
+        ShellCommand.__init__(self, **kwargs)
+
+    def describe(self, done=False):
+        return ["Wget symbols"]
+
+    def start(self):
+        buildURL = self.getProperty('fileURL')
+
+        for suffix in self._suffixes:
+            if buildURL.endswith(suffix):
+                self.symbolsURL = buildURL[:-len(suffix)] + '.crashreporter-symbols.zip'
+                break
+
+        symbolsFile = self.symbolsURL.split('/')[-1]
+        self.setProperty('symbolsFile', symbolsFile)
+        self.setCommand(['wget', '-nv', '-N', self.symbolsURL])
+        ShellCommand.start(self)
+
+
+class MozillaUnpackSymbols(ShellCommand):
+    def __init__(self, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+
+    def describe(self, done=False):
+        return ["Unpack symbols"]
+
+    def start(self):
+        self.setCommand(['unzip', '-o', '-d', 'symbols', self.getProperty('symbolsFile')])
+        ShellCommand.start(self)
+
+
+class MozillaInstallZip(ShellCommand):
+    """Install given file, unzipping to executablePath"""
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["unzip", "-o"]
+    
+    def describe(self, done=False):
+        return ["Install zip"]
+    
+    def start(self):
+        # removed the mkdir because this happens on the master, not the slave
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        if None != re.search('ERROR', cmd.logs['stdio'].getText()):
+            return FAILURE
+        if None != re.search('Usage:', cmd.logs['stdio'].getText()):
+            return FAILURE
+        return SUCCESS
+    
+
+class MozillaUpdateConfig(ShellCommand):
+    """Configure YAML file for run_tests.py"""
+   
+    def __init__(self, branch, executablePath, branchName, addOptions=[],
+                 useSymbols=False, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(branch=branch, executablePath=executablePath,
+                                 branchName=branchName, addOptions=addOptions,
+                                 useSymbols=useSymbols)
+        self.branch = branch
+        self.exePath = executablePath
+        self.branchName = branchName
+        self.addOptions = addOptions
+        self.useSymbols = useSymbols
+
+    def setBuild(self, build):
+        ShellCommand.setBuild(self, build)
+        self.title = build.slavename
+        self.changes = build.source.changes
+        self.buildid = strftime("%Y%m%d%H%M", localtime(self.changes[-1].when))
+
+
+        extraopts = copy.copy(self.addOptions)
+        if self.useSymbols:
+            extraopts += ['--symbolsPath', '../symbols']
+
+        if not self.command:
+            self.setCommand(["python", "PerfConfigurator.py", "-v", "-e", self.exePath, "-t", self.title, "-b", self.branch, "-d", self.buildid, '--branchName', self.branchName] + extraopts)
+
+    def describe(self, done=False):
+        return ["Update config"]
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        stdioText = cmd.logs['stdio'].getText()
+        if None != re.search('ERROR', stdioText):
+            return FAILURE
+        if None != re.search('USAGE:', stdioText):
+            return FAILURE
+        configFileMatch = re.search('outputName\s*=\s*(\w*?.yml)', stdioText)
+        if not configFileMatch:
+            return FAILURE
+        else:
+            self.setProperty("configFile", configFileMatch.group(1))
+        return SUCCESS
+    
+
+class MozillaRunPerfTests(ShellCommand):
+    """Run the performance tests"""
+    
+    def __init__(self, branch, command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(branch=branch, command=command)
+        self.branch = branch
+        self.command = command or ["python", "run_tests.py"]
+    
+    def describe(self, done=False):
+        return ["Run performance tests"]
+    
+    def createSummary(self, log):
+        summary = []
+        for line in log.readlines():
+            if "RETURN:" in line:
+                summary.append(line.replace("RETURN:", "TinderboxPrint:"))
+            if "FAIL:" in line:
+                summary.append(line.replace("FAIL:", "TinderboxPrint:FAIL:"))
+        self.addCompleteLog('summary', "\n".join(summary))
+    
+    def start(self):
+        """docstring for start"""
+        self.command = copy.copy(self.command)
+        self.command.append(self.getProperty("configFile"))
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        stdioText = cmd.logs['stdio'].getText()
+        if SUCCESS != superResult:
+            return FAILURE
+        if None != re.search('ERROR', stdioText):
+            return FAILURE
+        if None != re.search('USAGE:', stdioText):
+            return FAILURE
+        if None != re.search('FAIL:', stdioText):
+            return WARNINGS
+        return SUCCESS
+
+class MozillaInstallTarBz2(ShellCommand):
+    """Install given file, unzipping to executablePath"""
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["tar", "-jvxf"]
+    
+    def describe(self, done=False):
+        return ["Install tar.bz2"]
+    
+    def start(self):
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        return SUCCESS
+
+class MozillaInstallTarGz(ShellCommand):
+    """Install given file, unzipping to executablePath"""
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["tar", "-zvxf"]
+    
+    def describe(self, done=False):
+        return ["Install tar.gz"]
+    
+    def start(self):
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        return SUCCESS
+
+class MozillaInstallDmg(ShellCommand):
+    """Install given file, copying to workdir"""
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["bash", "installdmg.sh"]
+    
+    def describe(self, done=False):
+        return ["Install dmg"]
+    
+    def start(self):
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        return SUCCESS
+
+class MozillaInstallDmgEx(ShellCommand):
+    """Install given file, copying to workdir"""
+    #This is a temporary class to test the new InstallDmg script without affecting the production mac machines
+    # if this works everything should be switched over the using it
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["expect", "installdmg.ex"]
+    
+    def describe(self, done=False):
+        return ["Install dmg"]
+    
+    def start(self):
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        return SUCCESS
+
+class TalosFactory(BuildFactory):
+    """Create working talos build factory"""
+
+    winClean   = ["touch temp.zip &", "rm", "-rf", "*.zip", "talos/", "firefox/", "symbols/"]
+    macClean   = "rm -vrf *"
+    linuxClean = "rm -vrf *"
+
+    def __init__(self, OS, envName, buildBranch, branchName, fetchSymbols, configOptions, buildPath, talosCmd, customManifest='', cvsRoot=":pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot"):
+        BuildFactory.__init__(self)
+        if OS in ('linux', 'linuxbranch',):
+            cleanCmd = self.linuxClean
+        elif OS in ('win',):
+            cleanCmd = self.winClean
+        else:
+            cleanCmd = self.macClean
+        self.addStep(ShellCommand(
+                           workdir=".",
+                           description="Cleanup",
+                           command=cleanCmd,
+                           env=MozillaEnvironments[envName]))
+        self.addStep(FileDownload(
+                           mastersrc="scripts/count_and_reboot.py",
+                           slavedest="count_and_reboot.py",
+                           workdir="."))
+        self.addStep(ShellCommand(
+                           command=["cvs", "-d", cvsRoot, "co", "-d", "talos",
+                                    "mozilla/testing/performance/talos"],
+                           workdir=".",
+                           description="checking out talos",
+                           haltOnFailure=True,
+                           flunkOnFailure=True,
+                           env=MozillaEnvironments[envName]))
+        self.addStep(FileDownload(
+                           mastersrc="scripts/generate-tpcomponent.py",
+                           slavedest="generate-tpcomponent.py",
+                           workdir="talos/page_load_test"))
+        if customManifest != '':
+            self.addStep(FileDownload(
+                           mastersrc=customManifest,
+                           slavedest="manifest.txt",
+                           workdir="talos/page_load_test"))
+        self.addStep(ShellCommand(
+                           command=["python", "generate-tpcomponent.py"],
+                           workdir="talos/page_load_test",
+                           description="setting up pageloader",
+                           haltOnFailure=True,
+                           flunkOnFailure=True,
+                           env=MozillaEnvironments[envName]))
+        self.addStep(MozillaWget(
+                           workdir=".",
+                           branch=buildBranch,
+                           env=MozillaEnvironments[envName]))
+        if fetchSymbols:
+            self.addStep(MozillaWgetSymbols(workdir="."))
+            self.addStep(MozillaUnpackSymbols(workdir="."))
+        #install the browser, differs based upon platform
+        if OS == 'linux':
+            self.addStep(MozillaInstallTarBz2(
+                               workdir=".",
+                               branch=buildBranch,
+                               haltOnFailure=True,
+                               env=MozillaEnvironments[envName]))
+        elif OS == 'linuxbranch': #special case for old linux builds
+            self.addStep(MozillaInstallTarGz(
+                           workdir=".",
+                           branch=buildBranch,
+                           haltOnFailure=True,
+                           env=MozillaEnvironments[envName]))
+        elif OS == 'win':
+            self.addStep(MozillaInstallZip(
+                               workdir=".",
+                               branch=buildBranch,
+                               haltOnFailure=True,
+                               env=MozillaEnvironments[envName]))
+            self.addStep(ShellCommand(
+                               workdir="firefox/",
+                               flunkOnFailure=False,
+                               warnOnFailure=False,
+                               description="chmod files (see msys bug)",
+                               command=["chmod", "-v", "-R", "a+x", "."],
+                               env=MozillaEnvironments[envName]))
+        elif OS == 'tiger':
+            self.addStep(FileDownload(
+                           mastersrc="scripts/installdmg.sh",
+                           slavedest="installdmg.sh",
+                           workdir="."))
+            self.addStep(MozillaInstallDmg(
+                               workdir=".",
+                               branch=buildBranch,
+                               haltOnFailure=True,
+                               env=MozillaEnvironments[envName]))
+        else: #leopard
+            self.addStep(FileDownload(
+                           mastersrc="scripts/installdmg.ex",
+                           slavedest="installdmg.ex",
+                           workdir="."))
+            self.addStep(MozillaInstallDmgEx(
+                               workdir=".",
+                               branch=buildBranch,
+                               haltOnFailure=True,
+                               env=MozillaEnvironments[envName]))
+        self.addStep(MozillaUpdateConfig(
+                           workdir="talos/",
+                           branch=buildBranch,
+                           branchName=branchName,
+                           haltOnFailure=True,
+                           executablePath=buildPath,
+                           addOptions=configOptions,
+                           env=MozillaEnvironments[envName],
+                           useSymbols=fetchSymbols))
+        self.addStep(MozillaRunPerfTests(
+                           warnOnWarnings=True,
+                           workdir="talos/",
+                           branch=buildBranch,
+                           timeout=21600,
+                           haltOnFailure=False,
+                           command=talosCmd,
+                           env=MozillaEnvironments[envName]))
+        self.addStep(ShellCommand(
+                           flunkOnFailure=False,
+                           warnOnFailure=False,
+                           alwaysRun=True,
+                           workdir='.',
+                           description="reboot after 1 test run",
+                           command=["python", "count_and_reboot.py", "-f", "../talos_count.txt", "-n", "1", "-z"],
+                           env=MozillaEnvironments[envName]))
+
+
+#
+# Just like MozillaRunPerfTests, except:
+#  - hackTbPrint/printId to fix multiple test run tinderboxPrints
+#  - remove describe() since it's too generic for multiple test runs
+#  - remove start() since I'm already passing the command
+#
+class MaemoRunPerfTests(ShellCommand):
+    """Run the performance tests"""
+       
+    def __init__(self, hackTbPrint=None, printId=1, **kwargs):
+        if 'branch' in kwargs:
+            self.branch = kwargs['branch']
+        if not 'command' in kwargs:
+            kwargs['command'] = ["python", "run_tests.py"]
+        ShellCommand.__init__(self, **kwargs)
+        self.hackTbPrint = hackTbPrint
+        self.printId = printId
+    
+    def createSummary(self, log):
+        summary = []
+        for line in log.readlines():
+            if "RETURN:" in line:
+                # The RETURN: messages aren't designed to have multiple
+                # test runs; hacking them to be less noisy
+                if (self.hackTbPrint):
+                    line.replace("<br>","")
+                    if "graph.html" in line:
+                        if "| " in line:
+                            p = re.compile(r'\s*\|\s*')
+                            line = 'RETURN:<small>%s</small>' % \
+                                   p.split(line)[1]
+                    else:
+                        if not self.printId:
+                            continue
+                        if ("id:" not in line):
+                            if ("rev:" not in line):
+                                continue
+                            else:
+                                line = "%s<br>" % line
+                summary.append(line.replace("RETURN:", "TinderboxPrint:"))
+            if "FAIL:" in line:
+                summary.append(line.replace("FAIL:", "TinderboxPrint:FAIL:"))
+        self.addCompleteLog('summary', "\n".join(summary))
+            
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        stdioText = cmd.logs['stdio'].getText()
+        if SUCCESS != superResult:
+            return FAILURE
+        if None != re.search('ERROR', stdioText):
+            return FAILURE
+        if None != re.search('USAGE:', stdioText):
+            return FAILURE
+        if None != re.search('FAIL:', stdioText):
+            return WARNINGS
+        return SUCCESS
+
+#
+# Offshoot of TalosFactory, without any of the checkouts and with a
+# number of options to make running on the mobile devices possible.
+#
+class MaemoTalosFactory(BuildFactory):
+    """Create maemo talos build factory"""
+    
+    maemoClean = "rm -rf fennec fennec*.tar.bz2"
+
+    def __init__(self,
+                activeTests={
+                    'ts':     20,
+                    'tp':     20,
+                    'tdhtml': 20,
+                    'tsvg':   20,
+                    'twinopen':   20,
+                    'tsspider':   20,
+                    'tgfx':   20,
+                },
+                talosConfigFile='sample.config',
+                resultsServer=None,
+                builderName = "unnamed",
+                disableJit = 1,
+                hackTbPrint = 0,
+                branch = None,
+                baseDir = "/media/mmc1",
+    ):
+        BuildFactory.__init__(self)
+        self.baseDir = baseDir
+        self.branch = branch
+        self.disableJit = disableJit
+        self.hackTbPrint = hackTbPrint
+
+        self.addStep(ShellCommand(
+                        command=["ifconfig","-a"],
+                        description="IP",
+        ))
+        self.addStep(ShellCommand,
+            workdir=self.baseDir,
+            description="Cleanup",
+            command=self.maemoClean
+        )
+        self.addStep(MozillaWget,
+            workdir=self.baseDir,
+            branch=self.branch,
+            haltOnFailure=True
+        )
+        self.addStep(MozillaInstallTarBz2,
+            workdir=self.baseDir,
+            branch=self.branch,
+            haltOnFailure=True
+        )
+        self.addStep(ShellCommand,
+            workdir='%s/fennec' % self.baseDir,
+            description=["get", "info"],
+            command=['cat', 'application.ini', 'xulrunner/platform.ini']
+        )
+        if (self.disableJit):
+            self.addStep(ShellCommand,
+                        command = ["sh", "-x", "%s/talos/fix_jit.sh"%(self.baseDir)],
+                        description="disable JIT",
+            )
+        self.addStep(ShellCommand,
+                     command="echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor",
+                     description=['disable', 'scaling', 'governor'],
+                     haltOnFailure=True,
+        )
+        self.addStep(ShellCommand,
+                        command = ["cp", "-r", "chrome","components","/media/mmc1/fennec"],
+                        workdir = "%s/talos" % (self.baseDir),
+                        description="Copy pageloader",
+                        haltOnFailure=True,
+        )
+
+        firstTest = 1
+        for testName in activeTests.keys():
+            self.addStep(ShellCommand,
+#                        command=['python','PerfConfigurator.py','-v','-e','/media/mmc1/fennec/fennec','-t',builderName,'-b',self.branch,'--activeTests',testName,'--sampleConfig',talosConfigFile,'--noChrome','--resultsServer',resultsServer,'--resultsLink','/server/bulk.cgi','--output','local.config'],
+                        command='python PerfConfigurator.py -v -e %s/fennec/fennec -t `hostname` -b %s --activeTests %s --sampleConfig %s --browserWait %d --noChrome --oldresultsServer %s --oldresultsLink /server/bulk.cgi --output local.config' % (self.baseDir,self.branch,testName,talosConfigFile,activeTests[testName],resultsServer),
+                        workdir = "%s/talos" % (self.baseDir),
+                        description="Create config %s" % (testName),
+                        haltOnFailure=True,
+            )
+            self.addStep(ShellCommand(
+                        workdir = "%s/talos" % (self.baseDir),
+                        command=["cat","local.config"],
+                        description="Show config %s" % (testName),
+            ))
+            self.addStep(ShellCommand(
+                        workdir = ".",
+                        command="free; df -h",
+                        description="Check memory/disk",
+            ))
+            self.addStep(MaemoRunPerfTests,
+                        command=["python","run_tests.py","--noisy","--debug","local.config"],
+                        workdir = "%s/talos" % (self.baseDir),
+                        description="Run %s" % (testName),
+                        branch=self.branch,
+                        configFile="local.config",
+                        timeout=60 * 60,
+                        hackTbPrint=hackTbPrint,
+                        printId=firstTest,
+                        warnOnWarnings=True,
+                        haltOnFailure=False,
+            )
+            firstTest = 0
+        self.addStep(ShellCommand(
+                        command="reboot; sleep 600",
+                        warnOnFailure=False,
+                        flunkOnFailure=False,
+                        alwaysRun=True
+        ))
+
+
+
+def main(argv=None):
+    if argv is None:
+        argv = sys.argv
+    #BUG - need to come up with a new test case now that we aren't doing url scraping in the perfrunner code
+    #tester = LatestFileURL('http://stage.mozilla.org/pub/mozilla.org/firefox/tinderbox-builds/fx-win32-tbox-trunk/', "en-US.win32.zip")
+   # tester.testrun()
+    return 0
+
+if __name__ == '__main__':
+    main()
new file mode 100644
--- /dev/null
+++ b/mobile/master.cfg
@@ -0,0 +1,184 @@
+###########################################################################
+# mobile-staging master.cfg
+# Built largely from perf-staging/master.cfg, but will most likely also
+# contain unit tests.
+###########################################################################
+
+import os.path
+import re
+
+from buildbot.buildslave import BuildSlave
+
+from buildbot.process.factory import BuildFactory
+from buildbot.scheduler import Scheduler
+from buildbot.status import html, tinderbox
+from buildbot.status.mail import MailNotifier
+from tinderboxmailnotifier import TinderboxMailNotifier
+from buildbot.steps.shell import Compile, ShellCommand, WithProperties
+from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE, SKIPPED, EXCEPTION
+
+import perfrunner
+reload(perfrunner)
+from perfrunner import *
+
+import ftppoller
+reload(ftppoller)
+from ftppoller import FtpPoller
+
+
+MAEMO_SEARCHSTRING="en-US.linux-arm.tar.bz2"
+MAEMO_TRUNK_BUILDDIRS = [
+    "http://ftp.mozilla.org/pub/mozilla.org/firefox/tinderbox-builds/mobile-browser-linux-arm/",
+    "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mobile-browser/",
+    "http://10.250.3.10/maemo"
+]
+
+TINDERBOX_TREE="Mobile"
+RESULTS_SERVER="graphs.mozilla.org"
+
+c = BuildmasterConfig = {}
+
+##
+## Misc Config
+##
+
+c['debugPassword'] = "mozilla"
+c['projectName'] = "Talos"
+c['projectURL'] = "http://quality.mozilla.org/en/projects/automation/talos"
+c['buildbotURL'] = "http://staging-mobile-master.mozilla.org:8010"
+c['slavePortnum'] = 9010
+
+
+##
+## Slaves
+##
+
+c['slaves'] = [
+               BuildSlave("maemo-n810-01", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-02", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-03", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-04", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-05", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-06", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-07", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-08", "m0b1l3", max_builds=1),
+               BuildSlave("maemo-n810-09", "m0b1l3", max_builds=1),
+              ]
+
+##
+## Status
+##
+
+c['status'] = []
+c['status'].append(html.WebStatus(http_port=8010, allowForce=True))
+
+c['status'].append(MailNotifier(
+    fromaddr="talos.buildbot@build.mozilla.org",
+    sendToInterestedUsers=False,
+    extraRecipients=['aki@mozilla.com'],
+    mode="failing",
+    builders=None,
+    relayhost="smtp.mozilla.org"
+))
+
+c['status'].append(TinderboxMailNotifier(
+    fromaddr="talos.buildbot@build.mozilla.org",
+    tree=TINDERBOX_TREE,
+    extraRecipients=["tinderbox-daemon@tinderbox.mozilla.org"],
+    relayhost="smtp.mozilla.org",
+    builders=["N810 Talos Tp", "N810 Talos non-Tp", "N810 Talos Tp JIT"],
+    logCompression="bzip2"
+))
+
+
+##
+## Sources
+##
+
+c['change_source'] = []
+
+c['change_source'].append(FtpPoller(
+    tree = "mobile",
+    branch = "mobile-browser-maemo",
+    pollInterval = 1 * 60,
+    ftpURLs = MAEMO_TRUNK_BUILDDIRS,
+    searchString = MAEMO_SEARCHSTRING
+))
+
+
+##
+## Schedulers
+##
+
+c['schedulers'] = []
+
+c['schedulers'].append(MultiBuildScheduler(
+    name="maemo scheduler",
+    branch="mobile-browser-maemo",
+    treeStableTimer=1*60,
+    builderNames=[
+        'N810 Talos Tp',
+        'N810 Talos non-Tp',
+        'N810 Talos Tp JIT',
+    ]
+))
+
+maemoTalosStepsTp = MaemoTalosFactory(
+    activeTests={
+        'tp':     90,
+    },
+    talosConfigFile='mobile.config',
+    resultsServer=RESULTS_SERVER,
+    branch='mobile-browser',
+)
+
+maemoTalosStepsTpJIT = MaemoTalosFactory(
+    activeTests={
+        'tp':     90,
+    },
+    disableJit=0,
+    talosConfigFile='mobile.config',
+    resultsServer=RESULTS_SERVER,
+    branch='mobile-browser',
+)
+
+maemoTalosStepsNonTp = MaemoTalosFactory(
+    activeTests={
+        'ts':     60,
+        'tdhtml': 60,
+        'tsvg':   60,
+        'twinopen':   60,
+        'tsspider':   60,
+        'tgfx':   60,
+    },
+    talosConfigFile='mobile.config',
+    resultsServer=RESULTS_SERVER,
+    branch='mobile-browser',
+    hackTbPrint=1,
+)
+
+n810_trunk_tp = {
+    'name': "N810 Talos Tp",
+    'slavenames': ['maemo-n810-01', 'maemo-n810-02', 'maemo-n810-03'],
+    'builddir': "n810-trunk-tp",
+    'factory': maemoTalosStepsTp,
+    'category': "Mobile"
+}
+
+n810_trunk_non_tp = {
+    'name': "N810 Talos non-Tp",
+    'slavenames': ['maemo-n810-04', 'maemo-n810-05', 'maemo-n810-06'],
+    'builddir': "n810-trunk-non-tp",
+    'factory': maemoTalosStepsNonTp,
+    'category': "Mobile"
+}
+
+n810_trunk_tp_jit = {
+    'name': "N810 Talos Tp JIT",
+    'slavenames': ['maemo-n810-07', 'maemo-n810-08', 'maemo-n810-09'],
+    'builddir': "n810-trunk-tp-jit",
+    'factory': maemoTalosStepsTpJIT,
+    'category': "Mobile"
+}
+
+c['builders'] = [n810_trunk_tp, n810_trunk_non_tp, n810_trunk_tp_jit]
new file mode 100644
--- /dev/null
+++ b/mobile/perfrunner.py
@@ -0,0 +1,714 @@
+# -*- Python -*-
+
+from twisted.python import log
+from buildbot import buildset
+from buildbot.scheduler import Scheduler
+from buildbot.process.buildstep import BuildStep
+from buildbot.process.factory import BuildFactory
+from buildbot.buildset import BuildSet
+from buildbot.sourcestamp import SourceStamp
+from buildbot.steps.shell import ShellCommand, WithProperties
+from buildbot.steps.transfer import FileDownload
+from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE, SKIPPED, EXCEPTION
+import re, urllib, sys, os
+from time import strptime, strftime, localtime
+from datetime import datetime
+from os import path
+import copy
+
+MozillaEnvironments = { }
+
+# platform SDK location.  we can build both from one generic template.
+# modified from vc8 environment
+MozillaEnvironments['vc8perf'] = {
+    "MOZ_CRASHREPORTER_NO_REPORT": '1',
+    "MOZ_NO_REMOTE": '1',
+    "NO_EM_RESTART": '1',
+    "XPCOM_DEBUG_BREAK": 'warn',
+    "CYGWINBASE": 'C:\\cygwin',
+    "PATH": 'C:\\Python24;' + \
+            'C:\\Python24\\Scripts;' + \
+            'C:\\cygwin\\bin;' + \
+            'C:\\WINDOWS\\System32;' + \
+            'C:\\program files\\gnuwin32\\bin;' + \
+            'C:\\WINDOWS;'
+}
+
+MozillaEnvironments['linux'] = {
+    "MOZ_CRASHREPORTER_NO_REPORT": '1',
+    "MOZ_NO_REMOTE": '1',
+    "NO_EM_RESTART": '1',
+    "XPCOM_DEBUG_BREAK": 'warn',
+    "DISPLAY": ":0",
+}
+
+MozillaEnvironments['mac'] = {
+    "MOZ_NO_REMOTE": '1',
+    "NO_EM_RESTART": '1',
+    "XPCOM_DEBUG_BREAK": 'warn',
+    "MOZ_CRASHREPORTER_NO_REPORT": '1',
+    # for extracting dmg's
+    "PAGER": '/bin/cat',
+}
+
+class MultiBuildScheduler(Scheduler):
+    """Trigger N (default three) build requests based upon the same change request"""
+    def __init__(self, numberOfBuildsToTrigger=3, **kwargs):
+        self.numberOfBuildsToTrigger = numberOfBuildsToTrigger
+        Scheduler.__init__(self, **kwargs)
+
+    def fireTimer(self):
+        self.timer = None
+        self.nextBuildTime = None
+        changes = self.importantChanges + self.unimportantChanges
+        self.importantChanges = []
+        self.unimportantChanges = []
+
+        # submit
+        for i in range(0, self.numberOfBuildsToTrigger):
+            bs = buildset.BuildSet(self.builderNames, SourceStamp(changes=changes))
+            self.submitBuildSet(bs)
+
+
+class MozillaWget(ShellCommand):
+    """Download built Firefox client from dated staging directory."""
+    haltOnFailure = True
+    
+    def __init__(self, branch="HEAD", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(branch=branch, command=command)
+        self.branch = branch
+        self.command = command or ["wget"]
+
+    def setBuild(self, build):
+        ShellCommand.setBuild(self, build)
+        self.changes = build.source.changes
+        #a full url is always provided by sendchange
+        self.fileURL = self.changes[-1].files[0]
+        self.filename = os.path.basename(self.fileURL)
+        # Lie about when we started so the talos runs line up with builds on
+        # the waterfall
+        try:
+            timestamp = int(os.path.basename(os.path.dirname(self.fileURL)))
+            self.changes[-1].when = timestamp
+        except:
+            pass
+    
+    def getFilename(self):
+        return self.filename
+    
+    def describe(self, done=False):
+        return ["Wget Download"]
+    
+    def start(self):
+        if self.branch:
+            self.setProperty("fileURL", self.fileURL)
+            self.setProperty("filename", self.filename)
+        self.setCommand(["wget", "-nv", "-N", self.fileURL])
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        if None != re.search('ERROR', cmd.logs['stdio'].getText()):
+            return FAILURE
+        return SUCCESS
+
+
+class MozillaWgetSymbols(ShellCommand):
+    """Download the matching symbol package with a build."""
+    haltOnFailure = False
+    _suffixes = ('.tar.bz2', '.dmg', '.zip')
+
+    def __init__(self, **kwargs):
+        #def setBuild(self, build):
+        #    ShellCommand.setBuild(self, build)
+        ShellCommand.__init__(self, **kwargs)
+
+    def describe(self, done=False):
+        return ["Wget symbols"]
+
+    def start(self):
+        buildURL = self.getProperty('fileURL')
+
+        for suffix in self._suffixes:
+            if buildURL.endswith(suffix):
+                self.symbolsURL = buildURL[:-len(suffix)] + '.crashreporter-symbols.zip'
+                break
+
+        symbolsFile = self.symbolsURL.split('/')[-1]
+        self.setProperty('symbolsFile', symbolsFile)
+        self.setCommand(['wget', '-nv', '-N', self.symbolsURL])
+        ShellCommand.start(self)
+
+
+class MozillaUnpackSymbols(ShellCommand):
+    def __init__(self, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+
+    def describe(self, done=False):
+        return ["Unpack symbols"]
+
+    def start(self):
+        self.setCommand(['unzip', '-o', '-d', 'symbols', self.getProperty('symbolsFile')])
+        ShellCommand.start(self)
+
+
+class MozillaInstallZip(ShellCommand):
+    """Install given file, unzipping to executablePath"""
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["unzip", "-o"]
+    
+    def describe(self, done=False):
+        return ["Install zip"]
+    
+    def start(self):
+        # removed the mkdir because this happens on the master, not the slave
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        if None != re.search('ERROR', cmd.logs['stdio'].getText()):
+            return FAILURE
+        if None != re.search('Usage:', cmd.logs['stdio'].getText()):
+            return FAILURE
+        return SUCCESS
+    
+
+class MozillaUpdateConfig(ShellCommand):
+    """Configure YAML file for run_tests.py"""
+   
+    def __init__(self, branch, executablePath, branchName, addOptions=[],
+                 useSymbols=False, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(branch=branch, executablePath=executablePath,
+                                 branchName=branchName, addOptions=addOptions,
+                                 useSymbols=useSymbols)
+        self.branch = branch
+        self.exePath = executablePath
+        self.branchName = branchName
+        self.addOptions = addOptions
+        self.useSymbols = useSymbols
+
+    def setBuild(self, build):
+        ShellCommand.setBuild(self, build)
+        self.title = build.slavename
+        self.changes = build.source.changes
+        self.buildid = strftime("%Y%m%d%H%M", localtime(self.changes[-1].when))
+
+
+        extraopts = copy.copy(self.addOptions)
+        if self.useSymbols:
+            extraopts += ['--symbolsPath', '../symbols']
+
+        if not self.command:
+            self.setCommand(["python", "PerfConfigurator.py", "-v", "-e", self.exePath, "-t", self.title, "-b", self.branch, "-d", self.buildid, '--branchName', self.branchName] + extraopts)
+
+    def describe(self, done=False):
+        return ["Update config"]
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        stdioText = cmd.logs['stdio'].getText()
+        if None != re.search('ERROR', stdioText):
+            return FAILURE
+        if None != re.search('USAGE:', stdioText):
+            return FAILURE
+        configFileMatch = re.search('outputName\s*=\s*(\w*?.yml)', stdioText)
+        if not configFileMatch:
+            return FAILURE
+        else:
+            self.setProperty("configFile", configFileMatch.group(1))
+        return SUCCESS
+    
+
+class MozillaRunPerfTests(ShellCommand):
+    """Run the performance tests"""
+    
+    def __init__(self, branch, command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(branch=branch, command=command)
+        self.branch = branch
+        self.command = command or ["python", "run_tests.py"]
+    
+    def describe(self, done=False):
+        return ["Run performance tests"]
+    
+    def createSummary(self, log):
+        summary = []
+        for line in log.readlines():
+            if "RETURN:" in line:
+                summary.append(line.replace("RETURN:", "TinderboxPrint:"))
+            if "FAIL:" in line:
+                summary.append(line.replace("FAIL:", "TinderboxPrint:FAIL:"))
+        self.addCompleteLog('summary', "\n".join(summary))
+    
+    def start(self):
+        """docstring for start"""
+        self.command = copy.copy(self.command)
+        self.command.append(self.getProperty("configFile"))
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        stdioText = cmd.logs['stdio'].getText()
+        if SUCCESS != superResult:
+            return FAILURE
+        if None != re.search('ERROR', stdioText):
+            return FAILURE
+        if None != re.search('USAGE:', stdioText):
+            return FAILURE
+        if None != re.search('FAIL:', stdioText):
+            return WARNINGS
+        return SUCCESS
+
+class MozillaInstallTarBz2(ShellCommand):
+    """Install given file, unzipping to executablePath"""
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["tar", "-jvxf"]
+    
+    def describe(self, done=False):
+        return ["Install tar.bz2"]
+    
+    def start(self):
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        return SUCCESS
+
+class MozillaInstallTarGz(ShellCommand):
+    """Install given file, unzipping to executablePath"""
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["tar", "-zvxf"]
+    
+    def describe(self, done=False):
+        return ["Install tar.gz"]
+    
+    def start(self):
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        return SUCCESS
+
+class MozillaInstallDmg(ShellCommand):
+    """Install given file, copying to workdir"""
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["bash", "installdmg.sh"]
+    
+    def describe(self, done=False):
+        return ["Install dmg"]
+    
+    def start(self):
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        return SUCCESS
+
+class MozillaInstallDmgEx(ShellCommand):
+    """Install given file, copying to workdir"""
+    #This is a temporary class to test the new InstallDmg script without affecting the production mac machines
+    # if this works everything should be switched over the using it
+    
+    def __init__(self, filename="", branch="", command=None, **kwargs):
+        ShellCommand.__init__(self, **kwargs)
+        self.addFactoryArguments(filename=filename, branch=branch,
+                                 command=command)
+        self.filename = filename
+        self.branch = branch
+        self.command = command or ["expect", "installdmg.ex"]
+    
+    def describe(self, done=False):
+        return ["Install dmg"]
+    
+    def start(self):
+        if not self.filename:
+            if self.branch:
+                self.filename = self.getProperty("filename")
+            else:
+                return FAILURE
+        if self.filename:
+            self.command = self.command[:] + [self.filename]
+        ShellCommand.start(self)
+    
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        if SUCCESS != superResult:
+            return FAILURE
+        return SUCCESS
+
+class TalosFactory(BuildFactory):
+    """Create working talos build factory"""
+
+    winClean   = ["touch temp.zip &", "rm", "-rf", "*.zip", "talos/", "firefox/", "symbols/"]
+    macClean   = "rm -vrf *"
+    linuxClean = "rm -vrf *"
+
+    def __init__(self, OS, envName, buildBranch, branchName, fetchSymbols, configOptions, buildPath, talosCmd, customManifest='', cvsRoot=":pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot"):
+        BuildFactory.__init__(self)
+        if OS in ('linux', 'linuxbranch',):
+            cleanCmd = self.linuxClean
+        elif OS in ('win',):
+            cleanCmd = self.winClean
+        else:
+            cleanCmd = self.macClean
+        self.addStep(ShellCommand(
+                           workdir=".",
+                           description="Cleanup",
+                           command=cleanCmd,
+                           env=MozillaEnvironments[envName]))
+        self.addStep(FileDownload(
+                           mastersrc="scripts/count_and_reboot.py",
+                           slavedest="count_and_reboot.py",
+                           workdir="."))
+        self.addStep(ShellCommand(
+                           command=["cvs", "-d", cvsRoot, "co", "-d", "talos",
+                                    "mozilla/testing/performance/talos"],
+                           workdir=".",
+                           description="checking out talos",
+                           haltOnFailure=True,
+                           flunkOnFailure=True,
+                           env=MozillaEnvironments[envName]))
+        self.addStep(FileDownload(
+                           mastersrc="scripts/generate-tpcomponent.py",
+                           slavedest="generate-tpcomponent.py",
+                           workdir="talos/page_load_test"))
+        if customManifest != '':
+            self.addStep(FileDownload(
+                           mastersrc=customManifest,
+                           slavedest="manifest.txt",
+                           workdir="talos/page_load_test"))
+        self.addStep(ShellCommand(
+                           command=["python", "generate-tpcomponent.py"],
+                           workdir="talos/page_load_test",
+                           description="setting up pageloader",
+                           haltOnFailure=True,
+                           flunkOnFailure=True,
+                           env=MozillaEnvironments[envName]))
+        self.addStep(MozillaWget(
+                           workdir=".",
+                           branch=buildBranch,
+                           env=MozillaEnvironments[envName]))
+        if fetchSymbols:
+            self.addStep(MozillaWgetSymbols(workdir="."))
+            self.addStep(MozillaUnpackSymbols(workdir="."))
+        #install the browser, differs based upon platform
+        if OS == 'linux':
+            self.addStep(MozillaInstallTarBz2(
+                               workdir=".",
+                               branch=buildBranch,
+                               haltOnFailure=True,
+                               env=MozillaEnvironments[envName]))
+        elif OS == 'linuxbranch': #special case for old linux builds
+            self.addStep(MozillaInstallTarGz(
+                           workdir=".",
+                           branch=buildBranch,
+                           haltOnFailure=True,
+                           env=MozillaEnvironments[envName]))
+        elif OS == 'win':
+            self.addStep(MozillaInstallZip(
+                               workdir=".",
+                               branch=buildBranch,
+                               haltOnFailure=True,
+                               env=MozillaEnvironments[envName]))
+            self.addStep(ShellCommand(
+                               workdir="firefox/",
+                               flunkOnFailure=False,
+                               warnOnFailure=False,
+                               description="chmod files (see msys bug)",
+                               command=["chmod", "-v", "-R", "a+x", "."],
+                               env=MozillaEnvironments[envName]))
+        elif OS == 'tiger':
+            self.addStep(FileDownload(
+                           mastersrc="scripts/installdmg.sh",
+                           slavedest="installdmg.sh",
+                           workdir="."))
+            self.addStep(MozillaInstallDmg(
+                               workdir=".",
+                               branch=buildBranch,
+                               haltOnFailure=True,
+                               env=MozillaEnvironments[envName]))
+        else: #leopard
+            self.addStep(FileDownload(
+                           mastersrc="scripts/installdmg.ex",
+                           slavedest="installdmg.ex",
+                           workdir="."))
+            self.addStep(MozillaInstallDmgEx(
+                               workdir=".",
+                               branch=buildBranch,
+                               haltOnFailure=True,
+                               env=MozillaEnvironments[envName]))
+        self.addStep(MozillaUpdateConfig(
+                           workdir="talos/",
+                           branch=buildBranch,
+                           branchName=branchName,
+                           haltOnFailure=True,
+                           executablePath=buildPath,
+                           addOptions=configOptions,
+                           env=MozillaEnvironments[envName],
+                           useSymbols=fetchSymbols))
+        self.addStep(MozillaRunPerfTests(
+                           warnOnWarnings=True,
+                           workdir="talos/",
+                           branch=buildBranch,
+                           timeout=21600,
+                           haltOnFailure=False,
+                           command=talosCmd,
+                           env=MozillaEnvironments[envName]))
+        self.addStep(ShellCommand(
+                           flunkOnFailure=False,
+                           warnOnFailure=False,
+                           alwaysRun=True,
+                           workdir='.',
+                           description="reboot after 1 test run",
+                           command=["python", "count_and_reboot.py", "-f", "../talos_count.txt", "-n", "1", "-z"],
+                           env=MozillaEnvironments[envName]))
+
+
+#
+# Just like MozillaRunPerfTests, except:
+#  - hackTbPrint/printId to fix multiple test run tinderboxPrints
+#  - remove describe() since it's too generic for multiple test runs
+#  - remove start() since I'm already passing the command
+#
+class MaemoRunPerfTests(ShellCommand):
+    """Run the performance tests"""
+       
+    def __init__(self, hackTbPrint=None, printId=1, **kwargs):
+        if 'branch' in kwargs:
+            self.branch = kwargs['branch']
+        if not 'command' in kwargs:
+            kwargs['command'] = ["python", "run_tests.py"]
+        ShellCommand.__init__(self, **kwargs)
+        self.hackTbPrint = hackTbPrint
+        self.printId = printId
+    
+    def createSummary(self, log):
+        summary = []
+        for line in log.readlines():
+            if "RETURN:" in line:
+                # The RETURN: messages aren't designed to have multiple
+                # test runs; hacking them to be less noisy
+                if (self.hackTbPrint):
+                    line.replace("<br>","")
+                    if "graph.html" in line:
+                        if "| " in line:
+                            p = re.compile(r'\s*\|\s*')
+                            line = 'RETURN:<small>%s</small>' % \
+                                   p.split(line)[1]
+                    else:
+                        if not self.printId:
+                            continue
+                        if ("id:" not in line):
+                            if ("rev:" not in line):
+                                continue
+                            else:
+                                line = "%s<br>" % line
+                summary.append(line.replace("RETURN:", "TinderboxPrint:"))
+            if "FAIL:" in line:
+                summary.append(line.replace("FAIL:", "TinderboxPrint:FAIL:"))
+        self.addCompleteLog('summary', "\n".join(summary))
+            
+    def evaluateCommand(self, cmd):
+        superResult = ShellCommand.evaluateCommand(self, cmd)
+        stdioText = cmd.logs['stdio'].getText()
+        if SUCCESS != superResult:
+            return FAILURE
+        if None != re.search('ERROR', stdioText):
+            return FAILURE
+        if None != re.search('USAGE:', stdioText):
+            return FAILURE
+        if None != re.search('FAIL:', stdioText):
+            return WARNINGS
+        return SUCCESS
+
+#
+# Offshoot of TalosFactory, without any of the checkouts and with a
+# number of options to make running on the mobile devices possible.
+#
+class MaemoTalosFactory(BuildFactory):
+    """Create maemo talos build factory"""
+    
+    maemoClean = "rm -rf fennec fennec*.tar.bz2"
+
+    def __init__(self,
+                activeTests={
+                    'ts':     20,
+                    'tp':     20,
+                    'tdhtml': 20,
+                    'tsvg':   20,
+                    'twinopen':   20,
+                    'tsspider':   20,
+                    'tgfx':   20,
+                },
+                talosConfigFile='sample.config',
+                resultsServer=None,
+                builderName = "unnamed",
+                disableJit = 1,
+                hackTbPrint = 0,
+                branch = None,
+                baseDir = "/media/mmc1",
+    ):
+        BuildFactory.__init__(self)
+        self.baseDir = baseDir
+        self.branch = branch
+        self.disableJit = disableJit
+        self.hackTbPrint = hackTbPrint
+
+        self.addStep(ShellCommand(
+                        command=["ifconfig","-a"],
+                        description="IP",
+        ))
+        self.addStep(ShellCommand,
+            workdir=self.baseDir,
+            description="Cleanup",
+            command=self.maemoClean
+        )
+        self.addStep(MozillaWget,
+            workdir=self.baseDir,
+            branch=self.branch,
+            haltOnFailure=True
+        )
+        self.addStep(MozillaInstallTarBz2,
+            workdir=self.baseDir,
+            branch=self.branch,
+            haltOnFailure=True
+        )
+        self.addStep(ShellCommand,
+            workdir='%s/fennec' % self.baseDir,
+            description=["get", "info"],
+            command=['cat', 'application.ini', 'xulrunner/platform.ini']
+        )
+        if (self.disableJit):
+            self.addStep(ShellCommand,
+                        command = ["sh", "-x", "%s/talos/fix_jit.sh"%(self.baseDir)],
+                        description="disable JIT",
+            )
+        self.addStep(ShellCommand,
+                     command="echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor",
+                     description=['disable', 'scaling', 'governor'],
+                     haltOnFailure=True,
+        )
+        self.addStep(ShellCommand,
+                        command = ["cp", "-r", "chrome","components","/media/mmc1/fennec"],
+                        workdir = "%s/talos" % (self.baseDir),
+                        description="Copy pageloader",
+                        haltOnFailure=True,
+        )
+
+        firstTest = 1
+        for testName in activeTests.keys():
+            self.addStep(ShellCommand,
+#                        command=['python','PerfConfigurator.py','-v','-e','/media/mmc1/fennec/fennec','-t',builderName,'-b',self.branch,'--activeTests',testName,'--sampleConfig',talosConfigFile,'--noChrome','--resultsServer',resultsServer,'--resultsLink','/server/bulk.cgi','--output','local.config'],
+                        command='python PerfConfigurator.py -v -e %s/fennec/fennec -t `hostname` -b %s --activeTests %s --sampleConfig %s --browserWait %d --noChrome --oldresultsServer %s --oldresultsLink /server/bulk.cgi --output local.config' % (self.baseDir,self.branch,testName,talosConfigFile,activeTests[testName],resultsServer),
+                        workdir = "%s/talos" % (self.baseDir),
+                        description="Create config %s" % (testName),
+                        haltOnFailure=True,
+            )
+            self.addStep(ShellCommand(
+                        workdir = "%s/talos" % (self.baseDir),
+                        command=["cat","local.config"],
+                        description="Show config %s" % (testName),
+            ))
+            self.addStep(ShellCommand(
+                        workdir = ".",
+                        command="free; df -h",
+                        description="Check memory/disk",
+            ))
+            self.addStep(MaemoRunPerfTests,
+                        command=["python","run_tests.py","--noisy","--debug","local.config"],
+                        workdir = "%s/talos" % (self.baseDir),
+                        description="Run %s" % (testName),
+                        branch=self.branch,
+                        configFile="local.config",
+                        timeout=60 * 60,
+                        hackTbPrint=hackTbPrint,
+                        printId=firstTest,
+                        warnOnWarnings=True,
+                        haltOnFailure=False,
+            )
+            firstTest = 0
+        self.addStep(ShellCommand(
+                        command="reboot; sleep 600",
+                        warnOnFailure=False,
+                        flunkOnFailure=False,
+                        alwaysRun=True
+        ))
+
+
+
+def main(argv=None):
+    if argv is None:
+        argv = sys.argv
+    #BUG - need to come up with a new test case now that we aren't doing url scraping in the perfrunner code
+    #tester = LatestFileURL('http://stage.mozilla.org/pub/mozilla.org/firefox/tinderbox-builds/fx-win32-tbox-trunk/', "en-US.win32.zip")
+   # tester.testrun()
+    return 0
+
+if __name__ == '__main__':
+    main()