extras-buildsys/server UserInterface.py, NONE, 1.1 CONFIG.py, 1.7, 1.8 User.py, 1.1, 1.2 buildserver.py, 1.5, 1.6
Daniel Williams (dcbw)
fedora-extras-commits at redhat.com
Tue Jun 14 13:37:44 UTC 2005
Author: dcbw
Update of /cvs/fedora/extras-buildsys/server
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv4079/server
Modified Files:
CONFIG.py User.py buildserver.py
Added Files:
UserInterface.py
Log Message:
2005-06-14 Dan Williams <dcbw at redhat.com>
* server/CONFIG.py
- New options "ssl_frontend" and "ssl_buildclients". Only ssl_frontend is
used at this time. Setting it to True requires use of SSL to submit
build jobs and get server status. Setting it to False allows use of
xmlrpclib connections over HTTP, no certificates involved.
* server/User.py
- Add guest member to User class
* server/buildserver.py
- Move UserInterface class to UserInterface.py
- Re-enable the non-SSL XMLRPC server code
- Switch XMLRPC servers between SSL/non-SSL depending on CONFIG's
ssl_frontend value
- VerifiableSSLXMLRPCServer -> AuthenticatedSSLXMLRPCServer
* server/UserInterface.py
- Generalize UserInterface into a base class
- Implement UserInterfaceSSLAuth to handle SSL authenticated requests
- Implement UserInterfaceNoAuth to handle non-SSL requests
--- NEW FILE UserInterface.py ---
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Copyright 2005 Dan Williams <dcbw at redhat.com> and Red Hat, Inc.
import CONFIG
import sqlite
import smtplib
from email.MIMEText import MIMEText
import time
import sys
import os
from buildmaster import ensure_build_db_tables
def email_result(email, cvs_tag, resultstring, subject=None):
"""send 'resultstring' to email"""
msg = MIMEText(resultstring)
if not subject:
subject = 'Build Result: %s' % cvs_tag
msg['Subject'] = subject
msg['From'] = CONFIG.get('email_from')
email_to = '%s@%s' % (username, CONFIG.get('email_to_domain'))
msg['To'] = email_to
s = smtplib.SMTP()
s.connect()
s.sendmail(CONFIG.get('email_from'), [email_to], msg.as_string())
s.close()
class UserInterface:
"""
Base UserInterface class. NO AUTHENTICATION. Subclass this to provide some.
"""
def __init__(self, client_manager):
self.bcm = client_manager
self.dbcx = sqlite.connect("jobdb", encoding="utf-8", timeout=2)
self.curs = self.dbcx.cursor()
ensure_build_db_tables(self.dbcx)
def __del__(self):
self.dbcx.close()
def _insert_job(self, email, package, cvs_tag, target, buildreq, time):
# Insert request into the database
self.curs.execute('INSERT INTO jobs (uid, username, package,' \
' cvs_tag, target, buildreq, time_submitted, status)' \
' VALUES (NULL, "%s", "%s", "%s", "%s", "%s", %d, "%s")' \
% (email, package, cvs_tag, target, buildreq, time, 'waiting'))
self.dbcx.commit()
# Find the UID
self.curs.execute('SELECT uid FROM jobs WHERE username="%s" AND' \
' package="%s" AND cvs_tag="%s" AND target="%s" AND' \
' buildreq="%s" AND time_submitted=%d AND status="waiting"' \
% (email, package, cvs_tag, target, buildreq, time))
self.dbcx.commit()
item = self.curs.fetchone()
return item['uid']
def enqueue(self, email, package, cvs_tag, target, buildreq=None):
""" Accept a job to build and stuff it into the job database """
if CONFIG.get('use_srpm_not_cvs') == True:
email_result(email, cvs_tag, "Error setting up build for %s on "\
"%s: this server builds SRPMs, not CVS checkouts." % (cvs_tag, target))
return (-1, "This build server is set up for building SRPMS only. Use the 'enqueue_srpm' command instead.")
print "Request to enqueue '%s' tag '%s' for target '%s' (user '%s')" \
% (package, cvs_tag, target, email)
targets = CONFIG.get('targets')
jobid = -1
if not targets.has_key(target):
print "Error setting up build for %s on %s: target does not exist."\
% (cvs_tag, target)
email_result(email, cvs_tag, "Error setting up build for %s on "\
"%s: target does not exist." % (cvs_tag, target))
return (-1, "This build server does not support the target %s." % target)
else:
jobid = self._insert_job(email, package, cvs_tag, target, buildreq, time.time())
return (0, "Success: package has been queued.", jobid)
def enqueue_srpm(self, email, package, srpm_file, target, buildreq=None):
""" Accept a job to build from SRPM file and stuff it into the job database """
if CONFIG.get('use_srpm_not_cvs') == False:
email_result(email, srpm_file, "Error setting up build for %s on "\
"%s: this server builds CVS checkouts, not SRPMS." % (srpm_file, target))
return (-1, "This build server is set up for building from CVS. Use the 'enqueue' command instead.")
# We limit the database field to 255 chars
if len(srpm_file) > 255:
email_result(email, srpm_file, "Error setting up build for %s on "\
"%s: try using a shorter path to the SRPM (< 255 chars)." % (srpm_file, target))
return (-1, "Pathname to SRPM is limited to 255 characters.")
print "Request to enqueue '%s' file '%s' for target '%s' (user '%s')" \
% (package, srpm_file, target, email)
targets = CONFIG.get('targets')
jobid = -1
if not targets.has_key(target):
print "Error setting up build for %s on %s: target does not exist."\
% (srpm_file, target)
email_result(email, srpm_file, "Error setting up build for %s on "\
"%s: target does not exist." % (srpm_file, target))
return (-1, "This build server does not support the target %s." % target)
else:
jobid = self._insert_job(email, package, cvs_tag, target, buildreq, time.time())
return (0, "Success: package has been queued.", jobid)
def list_waiting_jobs(self):
self.curs.execute('SELECT uid, username, package, cvs_tag, target' \
' FROM jobs WHERE status="waiting"')
self.dbcx.commit()
data = self.curs.fetchall()
job_list = []
for row in data:
tempX = [ item for item in row]
job_list.append(tempX)
return job_list
def list_building_jobs(self):
self.curs.execute('SELECT uid, username, package, cvs_tag, target' \
' FROM jobs WHERE status="building"')
self.dbcx.commit()
data = self.curs.fetchall()
job_list = []
for row in data:
tempX = [ item for item in row]
job_list.append(tempX)
return job_list
def update_clients(self):
reload(CONFIG)
print "-----------------------------------------------------"
print " Looking for Build Clients..."
self.bcm.update_clients()
print "-----------------------------------------------------\n"
return (0, "Success.")
class UserInterfaceSSLAuth(UserInterface):
"""
Allow/Deny operations based on user privileges
"""
def enqueue(self, user, package, cvs_tag, target, buildreq=None):
if not user.own_jobs:
return (-1, "Insufficient privileges.")
return UserInterface.enqueue(self, user.email, package, cvs_tag, target, buildreq)
def enqueue_srpm(self, user, package, srpm_file, target, buildreq=None):
if not user.own_jobs:
return (-1, "Insufficient privileges.")
return UserInterface.enqueue_srpm(self, user.email, package, cvs_tag, target, buildreq)
def list_waiting_jobs(self, user):
return UserInterface.list_waiting_jobs(self)
def list_building_jobs(self, user):
return UserInterface.list_building_jobs(self)
def update_clients(self, user):
if not user.server_admin:
return (-1, "Insufficient privileges.")
return UserInterface.update_clients(self)
class UserInterfaceNoAuth(UserInterface):
"""
Allow all operations, NULL authentication
"""
def enqueue(self, email, package, cvs_tag, target, buildreq=None):
return UserInterface.enqueue(self, email, package, cvs_tag, target, buildreq)
def enqueue_srpm(self, email, package, srpm_file, target, buildreq=None):
return UserInterface.enqueue_srpm(self, email, package, cvs_tag, target, buildreq)
def list_waiting_jobs(self):
return UserInterface.list_waiting_jobs(self)
def list_building_jobs(self):
return UserInterface.list_building_jobs(self)
def update_clients(self):
return UserInterface.update_clients(self)
Index: CONFIG.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/server/CONFIG.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- CONFIG.py 14 Jun 2005 01:16:30 -0000 1.7
+++ CONFIG.py 14 Jun 2005 13:37:42 -0000 1.8
@@ -11,6 +11,15 @@
config_opts['log_url'] = "http://foo.foo.org/logs/"
config_opts['guest_allowed'] = True
+# SSL options
+#
+# ssl_frontend: True = package submitters need SSL to connect to the server
+config_opts['ssl_frontend'] = True
+# ssl_buildclients: True = all communication between server & build client
+# be over an SSL connecction
+config_opts['ssl_buildclients'] = True
+
+
SERVER_BASE_DIR = "/work/fedora-cvs/extras-buildsys/server"
# SSL Cert and key bits
Index: User.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/server/User.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- User.py 14 Jun 2005 01:16:30 -0000 1.1
+++ User.py 14 Jun 2005 13:37:42 -0000 1.2
@@ -20,10 +20,11 @@
class User:
- def __init__(self, email):
+ def __init__(self, email, guest):
if not email:
raise Exception
self.email = email
+ self.guest = guest
self.own_jobs = False
self.kill_any_job = False
self.modify_users = False
@@ -65,13 +66,13 @@
self.dbcx.commit()
item = self.curs.fetchone()
if item:
- user = User(email)
+ user = User(email, False)
user.own_jobs = item['own_jobs']
user.kill_any_job = item['kill_any_job']
user.modify_users = item['modify_users']
user.server_admin = item['server_admin']
else:
if CONFIG.get('guest_allowed'):
- user = User('guest at guest')
+ user = User('guest at guest', True)
return user
Index: buildserver.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/server/buildserver.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- buildserver.py 14 Jun 2005 01:16:30 -0000 1.5
+++ buildserver.py 14 Jun 2005 13:37:42 -0000 1.6
@@ -16,169 +16,23 @@
# written by Seth Vidal
-import time
import CONFIG
-import socket
import sys
import os
-import sqlite
-import smtplib
-from email.MIMEText import MIMEText
-import threading
from buildmaster import BuildMaster
-from buildmaster import ensure_build_db_tables
from client_manager import BuildClientManager
import SimpleHTTPSServer
import SimpleSSLXMLRPCServer
import User
+from UserInterface import UserInterfaceSSLAuth, UserInterfaceNoAuth
+import SimpleXMLRPCServer
-def email_result(username, cvs_tag, resultstring, subject=None):
- """send 'resultstring' to username"""
-
- msg = MIMEText(resultstring)
- if not subject:
- subject = 'Build Result: %s' % cvs_tag
- msg['Subject'] = subject
- msg['From'] = CONFIG.get('email_from')
- email_to = '%s@%s' % (username, CONFIG.get('email_to_domain'))
- msg['To'] = email_to
- s = smtplib.SMTP()
- s.connect()
- s.sendmail(CONFIG.get('email_from'), [email_to], msg.as_string())
- s.close()
-
-
-class UserInterface:
- def __init__(self, client_manager):
- self.bcm = client_manager
- self.dbcx = sqlite.connect("jobdb", encoding="utf-8", timeout=2)
- self.curs = self.dbcx.cursor()
- ensure_build_db_tables(self.dbcx)
-
- def __del__(self):
- self.dbcx.close()
-
- def _insert_job(self, username, package, cvs_tag, target, buildreq, time):
- # Insert request into the database
- self.curs.execute('INSERT INTO jobs (uid, username, package,' \
- ' cvs_tag, target, buildreq, time_submitted, status)' \
- ' VALUES (NULL, "%s", "%s", "%s", "%s", "%s", %d, "%s")' \
- % (username, package, cvs_tag, target, buildreq, time, 'waiting'))
- self.dbcx.commit()
-
- # Find the UID
- self.curs.execute('SELECT uid FROM jobs WHERE username="%s" AND' \
- ' package="%s" AND cvs_tag="%s" AND target="%s" AND' \
- ' buildreq="%s" AND time_submitted=%d AND status="waiting"' \
- % (username, package, cvs_tag, target, buildreq, time))
- self.dbcx.commit()
- item = self.curs.fetchone()
- return item['uid']
-
- def enqueue(self, user, username, package, cvs_tag, target, buildreq=None):
- """ Accept a job to build and stuff it into the job database """
-
- if not user.own_jobs:
- return (-1, "Insufficient privileges.")
-
- if CONFIG.get('use_srpm_not_cvs') == True:
- email_result(username, cvs_tag, "Error setting up build for %s on "\
- "%s: this server builds SRPMs, not CVS checkouts." % (cvs_tag, target))
- return (-1, "This build server is set up for building SRPMS only. Use the 'enqueue_srpm' command instead.")
-
- print "Request to enqueue '%s' tag '%s' for target '%s' (user '%s')" \
- % (package, cvs_tag, target, username)
- targets = CONFIG.get('targets')
- jobid = -1
- if not targets.has_key(target):
- print "Error setting up build for %s on %s: target does not exist."\
- % (cvs_tag, target)
- email_result(username, cvs_tag, "Error setting up build for %s on "\
- "%s: target does not exist." % (cvs_tag, target))
- return (-1, "This build server does not support the target %s." % target)
- else:
- jobid = self._insert_job(username, package, cvs_tag, target, buildreq, time.time())
- return (0, "Success: package has been queued.", jobid)
-
- def enqueue_srpm(self, user, username, package, srpm_file, target, buildreq=None):
- """ Accept a job to build from SRPM file and stuff it into the job database """
-
- if not user.own_jobs:
- return (-1, "Insufficient privileges.")
-
- if CONFIG.get('use_srpm_not_cvs') == False:
- email_result(username, srpm_file, "Error setting up build for %s on "\
- "%s: this server builds CVS checkouts, not SRPMS." % (srpm_file, target))
- return (-1, "This build server is set up for building from CVS. Use the 'enqueue' command instead.")
-
- # We limit the database field to 255 chars
- if len(srpm_file) > 255:
- email_result(username, srpm_file, "Error setting up build for %s on "\
- "%s: try using a shorter path to the SRPM (< 255 chars)." % (srpm_file, target))
- return (-1, "Pathname to SRPM is limited to 255 characters.")
-
- print "Request to enqueue '%s' file '%s' for target '%s' (user '%s')" \
- % (package, srpm_file, target, username)
- targets = CONFIG.get('targets')
- jobid = -1
- if not targets.has_key(target):
- print "Error setting up build for %s on %s: target does not exist."\
- % (srpm_file, target)
- email_result(username, srpm_file, "Error setting up build for %s on "\
- "%s: target does not exist." % (srpm_file, target))
- return (-1, "This build server does not support the target %s." % target)
- else:
- jobid = self._insert_job(username, package, cvs_tag, target, buildreq, time.time())
- return (0, "Success: package has been queued.", jobid)
-
-
- def list_waiting_jobs(self, user):
- self.curs.execute('SELECT uid, username, package, cvs_tag, target' \
- ' FROM jobs WHERE status="waiting"')
- self.dbcx.commit()
- data = self.curs.fetchall()
- job_list = []
- for row in data:
- tempX = [ item for item in row]
- job_list.append(tempX)
- return job_list
-
-
- def list_building_jobs(self, user):
- self.curs.execute('SELECT uid, username, package, cvs_tag, target' \
- ' FROM jobs WHERE status="building"')
- self.dbcx.commit()
- data = self.curs.fetchall()
- job_list = []
- for row in data:
- tempX = [ item for item in row]
- job_list.append(tempX)
- return job_list
-
-
- def update_clients(self, user):
- if not user.server_admin:
- return (-1, "Insufficient privileges.")
-
- reload(CONFIG)
- print "-----------------------------------------------------"
- print " Looking for Build Clients..."
- self.bcm.update_clients()
- print "-----------------------------------------------------\n"
- return (0, "Success.")
-
-
-# Unused for SSL connections, but keep around just in case
-# we give users the option of not using SSL at some later date
-#
-#class MyXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
-# def __init__(self, address):
-# self.allow_reuse_address = 1
-# SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=0)
+class AuthenticatedSSLXMLRPCServer(SimpleSSLXMLRPCServer.SimpleSSLXMLRPCServer):
+ """
+ SSL XMLRPC server that authenticates clients based on their certificate.
+ """
-
-class VerifiableSSLXMLRPCServer(SimpleSSLXMLRPCServer.SimpleSSLXMLRPCServer):
def __init__(self, certs, address):
SimpleSSLXMLRPCServer.SimpleSSLXMLRPCServer.__init__(self, certs, address, self.auth_cb)
self.authenticator = User.Authenticator()
@@ -198,6 +52,18 @@
return user
+class MyXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
+ """
+ Simple XMLRPC server that turns on address reuse.
+ """
+
+ def __init__(self, address):
+ self.allow_reuse_address = 1
+ SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=0)
+
+
+#################################################################
+
if __name__ == '__main__':
if len(sys.argv) < 2:
print "Usage:\n"
@@ -226,8 +92,13 @@
ui_certs['peer_ca_cert'] = CONFIG.get('ui_ca_cert')
# Create the BuildMaster XMLRPC server
- ui = UserInterface(bcm)
- bm_server = VerifiableSSLXMLRPCServer(ui_certs, (hostname, 8887))
+ ui = None
+ if CONFIG.get('ssl_frontend') == True:
+ ui = UserInterfaceSSLAuth(bcm)
+ bm_server = AuthenticatedSSLXMLRPCServer(ui_certs, (hostname, 8887))
+ else:
+ ui = UserInterfaceNoAuth(bcm)
+ bm_server = MyXMLRPCServer((hostname, 8887))
bm_server.register_instance(ui)
# SRPM fileserver
More information about the fedora-extras-commits
mailing list