Bump APScheduler to >=3.0

This patch upgrades zuul to support APScheduler 3.0. For the most
part, 3.0 was a rewrite but our changes seem to be limited.

Change-Id: I0c66b5998122c3f59ed06e3e7b3ab3199f94f478
Signed-off-by: Paul Belanger <pabelanger@redhat.com>
diff --git a/requirements.txt b/requirements.txt
index 6318a59..8da177a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,7 +12,7 @@
 statsd>=1.0.0,<3.0
 voluptuous>=0.7
 gear>=0.5.7,<1.0.0
-apscheduler>=2.1.1,<3.0
+apscheduler>=3.0
 PrettyTable>=0.6,<0.8
 babel>=1.0
 six>=1.6.0
diff --git a/zuul/trigger/timer.py b/zuul/trigger/timer.py
index c93a638..d42e3db 100644
--- a/zuul/trigger/timer.py
+++ b/zuul/trigger/timer.py
@@ -13,7 +13,8 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-import apscheduler.scheduler
+from apscheduler.schedulers.background import BackgroundScheduler
+from apscheduler.triggers.cron import CronTrigger
 import logging
 import voluptuous as v
 from zuul.model import EventFilter, TriggerEvent
@@ -26,7 +27,7 @@
 
     def __init__(self, trigger_config={}, sched=None, connection=None):
         super(TimerTrigger, self).__init__(trigger_config, sched, connection)
-        self.apsched = apscheduler.scheduler.Scheduler()
+        self.apsched = BackgroundScheduler()
         self.apsched.start()
 
     def _onTrigger(self, pipeline_name, timespec):
@@ -62,7 +63,7 @@
 
     def postConfig(self):
         for job in self.apsched.get_jobs():
-            self.apsched.unschedule_job(job)
+            job.remove()
         for pipeline in self.sched.layout.pipelines.values():
             for ef in pipeline.manager.event_filters:
                 if ef.trigger != self:
@@ -81,14 +82,11 @@
                         second = parts[5]
                     else:
                         second = None
-                    self.apsched.add_cron_job(self._onTrigger,
-                                              day=dom,
-                                              day_of_week=dow,
-                                              hour=hour,
-                                              minute=minute,
-                                              second=second,
-                                              args=(pipeline.name,
-                                                    timespec,))
+                    trigger = CronTrigger(day=dom, day_of_week=dow, hour=hour,
+                                          minute=minute, second=second)
+
+                    self.apsched.add_job(self._onTrigger, trigger=trigger,
+                                         args=(pipeline.name, timespec,))
 
 
 def getSchema():