depot.py revision 25
0N/A#!/usr/bin/python
20N/A#
20N/A# CDDL HEADER START
20N/A#
20N/A# The contents of this file are subject to the terms of the
20N/A# Common Development and Distribution License (the "License").
20N/A# You may not use this file except in compliance with the License.
20N/A#
20N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
20N/A# or http://www.opensolaris.org/os/licensing.
20N/A# See the License for the specific language governing permissions
20N/A# and limitations under the License.
20N/A#
20N/A# When distributing Covered Code, include this CDDL HEADER in each
20N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
20N/A# If applicable, add the following below this CDDL HEADER, with the
20N/A# fields enclosed by brackets "[]" replaced with your own identifying
20N/A# information: Portions Copyright [yyyy] [name of copyright owner]
20N/A#
20N/A# CDDL HEADER END
20N/A#
20N/A# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
20N/A# Use is subject to license terms.
20N/A#
20N/A
20N/A# pkg.depotd - package repository daemon
20N/A
0N/Aimport BaseHTTPServer
0N/Aimport os
0N/Aimport re
0N/Aimport sha
0N/Aimport shutil
0N/Aimport time
0N/Aimport urllib
0N/A
14N/Aimport pkg.config as config
14N/Aimport pkg.content as content
14N/Aimport pkg.dependency as dependency
14N/Aimport pkg.fmri as fmri
14N/Aimport pkg.image as image
0N/Aimport pkg.version as version
14N/A
14N/Aimport pkg.server.catalog as catalog
14N/Aimport pkg.server.package as package
14N/Aimport pkg.server.transaction as trans
14N/A
14N/A# in_flight_trans needs to be rebuilt on restart
14N/Ain_flight_trans = {}
14N/A
0N/Adef catalog(scfg, request):
0N/A """The marshalled form of the catalog is
0N/A
0N/A pkg_name (release (branch (sequence ...) ...) ...)
0N/A
0N/A since we know that the server is only to report packages for which it
0N/A can offer a record.
0N/A """
0N/A
0N/A request.send_response(200)
0N/A request.send_header('Content-type', 'text/plain')
0N/A request.end_headers()
0N/A request.wfile.write('''GET URI %s ; headers %s''' % (request.path, request.headers))
0N/A
0N/Adef trans_open(scfg, request):
14N/A # XXX Authentication will be handled by virtue of possessing a signed
0N/A # certificate (or a more elaborate system).
0N/A t = trans.Transaction()
14N/A
0N/A ret = t.open(scfg, request)
0N/A if ret == 200:
0N/A in_flight_trans[t.get_basename()] = t
14N/A
14N/A request.send_response(200)
14N/A request.send_header('Content-type', 'text/plain')
0N/A request.send_header('Transaction-ID', t.get_basename())
0N/A request.end_headers()
0N/A elif ret == 400:
0N/A request.send_response(400)
0N/A else:
0N/A request.send_response(500)
0N/A
0N/A
0N/Adef trans_close(scfg, request):
0N/A # Pull transaction ID from headers.
0N/A m = re.match("^/close/(.*)", request.path)
0N/A trans_id = m.group(1)
0N/A
14N/A # XXX KeyError?
14N/A t = in_flight_trans[trans_id]
14N/A t.close(request)
14N/A del in_flight_trans[trans_id]
14N/A
14N/Adef trans_abandon(scfg, request):
0N/A # Pull transaction ID from headers.
0N/A m = re.match("^/abandon/(.*)", request.path)
0N/A trans_id = m.group(1)
0N/A
0N/A t = in_flight_trans[trans_id]
0N/A t.abandon(request)
0N/A del in_flight_trans[trans_id]
0N/A
0N/Adef trans_add(scfg, request):
0N/A m = re.match("^/add/([^/]*)/(.*)", request.path)
0N/A trans_id = m.group(1)
0N/A type = m.group(2)
0N/A
0N/A t = in_flight_trans[trans_id]
0N/A t.add_content(request, type)
0N/A
0N/Aif "PKG_REPO" in os.environ:
0N/A scfg = config.SvrConfig(os.environ["PKG_REPO"])
0N/Aelse:
0N/A scfg = config.SvrConfig("/var/pkg/repo")
0N/A
0N/Aclass pkgHandler(BaseHTTPServer.BaseHTTPRequestHandler):
0N/A
0N/A def do_GET(self):
0N/A if re.match("^/catalog$", self.path):
0N/A catalog(scfg, self)
20N/A elif re.match("^/open/(.*)$", self.path):
21N/A trans_open(scfg, self)
21N/A elif re.match("^/close/(.*)$", self.path):
21N/A trans_close(scfg, self)
0N/A elif re.match("^/abandon/(.*)$", self.path):
0N/A trans_abandon(scfg, self)
0N/A elif re.match("^/add/(.*)$", self.path):
0N/A trans_add(scfg, self)
0N/A elif re.match("^/$", self.path) or re.match("^/index.html", self.path):
0N/A self.send_response(200)
0N/A self.send_header('Content-type', 'text/html')
0N/A self.end_headers()
0N/A self.wfile.write("""<html><body><h1><code>pkg</code> server ok</h1>\n""")
0N/A self.wfile.write("""</body></html>""")
0N/A else:
0N/A self.send_response(404)
0N/A self.send_header('Content-type', 'text/plain')
0N/A self.end_headers()
0N/A self.wfile.write('''404 GET URI %s ; headers %s''' % (self.path, self.headers))
0N/A
0N/A
0N/A def do_PUT(self):
0N/A self.send_response(200)
0N/A self.send_header('Content-type', 'text/plain')
0N/A self.end_headers()
0N/A self.wfile.write('''PUT URI %s ; headers %s''' % (self.path, self.headers))
0N/A
0N/A def do_POST(self):
0N/A if re.match("^/add/(.*)$", self.path):
0N/A trans_add(scfg, self)
0N/A else:
0N/A self.send_response(404)
0N/A
0N/A def do_DELETE(self):
0N/A self.send_response(200)
0N/A self.send_header('Content-type', 'text/plain')
0N/A self.end_headers()
0N/A self.wfile.write('''URI %s ; headers %s''' % (self.path, self.headers))
0N/A
0N/Aif __name__ == "__main__":
scfg.init_dirs()
server = BaseHTTPServer.HTTPServer(('', 10000), pkgHandler)
server.serve_forever()