Add JenkinsManager
Same idea as a ProviderManager: serialize changes to each jenkins server (with a rate limit). Change-Id: I631d50dcfd13c29d2802c192d6e1ac7889256a90changes/14/43014/2
parent
8dc6c870f2
commit
0ec2246514
@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (C) 2011-2013 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
#
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
|
||||
import myjenkins
|
||||
import fakeprovider
|
||||
from task_manager import Task, TaskManager
|
||||
|
||||
|
||||
class CreateNodeTask(Task):
|
||||
def main(self, jenkins):
|
||||
if 'credentials_id' in self.args:
|
||||
launcher_params = {'port': 22,
|
||||
'credentialsId': self.args['credentials_id'],
|
||||
'host': self.args['host']}
|
||||
else:
|
||||
launcher_params = {'port': 22,
|
||||
'username': self.args['username'],
|
||||
'privatekey': self.args['private_key'],
|
||||
'host': self.args['host']}
|
||||
try:
|
||||
jenkins.create_node(
|
||||
name=self.args['name'],
|
||||
numExecutors=self.args['executors'],
|
||||
nodeDescription=self.args['description'],
|
||||
remoteFS=self.args['root'],
|
||||
labels=self.args['labels'],
|
||||
exclusive=True,
|
||||
launcher='hudson.plugins.sshslaves.SSHLauncher',
|
||||
launcher_params=launcher_params)
|
||||
except myjenkins.JenkinsException as e:
|
||||
if 'already exists' in str(e):
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
class NodeExistsTask(Task):
|
||||
def main(self, jenkins):
|
||||
return jenkins.node_exists(self.args['name'])
|
||||
|
||||
|
||||
class DeleteNodeTask(Task):
|
||||
def main(self, jenkins):
|
||||
return jenkins.delete_node(self.args['name'])
|
||||
|
||||
|
||||
class JenkinsManager(TaskManager):
|
||||
log = logging.getLogger("nodepool.JenkinsManager")
|
||||
|
||||
def __init__(self, target):
|
||||
super(JenkinsManager, self).__init__(None, target.name, target.rate)
|
||||
self.target = target
|
||||
self._client = self._getClient()
|
||||
|
||||
def _getClient(self):
|
||||
if self.target.jenkins_apikey == 'fake':
|
||||
return fakeprovider.FakeJenkins()
|
||||
return myjenkins.Jenkins(self.target.jenkins_url,
|
||||
self.target.jenkins_user,
|
||||
self.target.jenkins_apikey)
|
||||
|
||||
def createNode(self, name, host, description, labels, executors, root,
|
||||
credentials_id=None, username=None, private_key=None):
|
||||
args = dict(name=name, host=host, description=description,
|
||||
labels=labels, executors=executors, root=root)
|
||||
if credentials_id:
|
||||
args['credentials_id'] = credentials_id
|
||||
else:
|
||||
args['username'] = username
|
||||
args['private_key'] = private_key
|
||||
return self.submitTask(CreateNodeTask(**args))
|
||||
|
||||
def nodeExists(self, name):
|
||||
return self.submitTask(NodeExistsTask(name=name))
|
||||
|
||||
def deleteNode(self, name):
|
||||
return self.submitTask(DeleteNodeTask(name=name))
|
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (C) 2011-2013 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
#
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
import threading
|
||||
import Queue
|
||||
import logging
|
||||
import time
|
||||
|
||||
|
||||
class Task(object):
|
||||
def __init__(self, **kw):
|
||||
self._wait_event = threading.Event()
|
||||
self._exception = None
|
||||
self._traceback = None
|
||||
self._result = None
|
||||
self.args = kw
|
||||
|
||||
def done(self, result):
|
||||
self._result = result
|
||||
self._wait_event.set()
|
||||
|
||||
def exception(self, e, tb):
|
||||
self._exception = e
|
||||
self._traceback = tb
|
||||
self._wait_event.set()
|
||||
|
||||
def wait(self):
|
||||
self._wait_event.wait()
|
||||
if self._exception:
|
||||
raise self._exception, None, self._traceback
|
||||
return self._result
|
||||
|
||||
def run(self, client):
|
||||
try:
|
||||
self.done(self.main(client))
|
||||
except Exception as e:
|
||||
self.exception(e, sys.exc_info()[2])
|
||||
|
||||
|
||||
class TaskManager(threading.Thread):
|
||||
log = logging.getLogger("nodepool.ProviderManager")
|
||||
|
||||
def __init__(self, client, name, rate):
|
||||
super(TaskManager, self).__init__()
|
||||
self.daemon = True
|
||||
self.queue = Queue.Queue()
|
||||
self._running = True
|
||||
self.name = name
|
||||
self.rate = float(rate)
|
||||
self._client = None
|
||||
|
||||
def stop(self):
|
||||
self._running = False
|
||||
self.queue.put(None)
|
||||
|
||||
def run(self):
|
||||
last_ts = 0
|
||||
while self._running:
|
||||
task = self.queue.get()
|
||||
if not task:
|
||||
continue
|
||||
while True:
|
||||
delta = time.time() - last_ts
|
||||
if delta >= self.rate:
|
||||
break
|
||||
time.sleep(self.rate - delta)
|
||||
self.log.debug("Manager %s running task %s" % (self.name, task))
|
||||
task.run(self._client)
|
||||
last_ts = time.time()
|
||||
self.queue.task_done()
|
||||
|
||||
def submitTask(self, task):
|
||||
self.queue.put(task)
|
||||
return task.wait()
|
Loading…
Reference in New Issue