Print this page
305 http_proxy value needs more checking for valid url syntax
2341 Client should be more conservative about closing sockets
4235 Misleading "node name" unknown messages when http_proxy set incorrectly
4495 Want ability to cancel individual file downloads
8902 Need a transport that downloads files by GET
9508 Captive portal test only run during catalog refresh
9613 Implicit refresh should raise InvalidDepotResponseException
9615 EOL clientside search v0
9629 EOL clientside support for filelist
9630 Hostile depot should live with other depot code
9631 HTTPS transport should be more rigorous in verification
9670 More specific error exceptions requested from search
9686 network operations should use accept-encoding when appropriate
9715 The info() operation should use the activity_lock
| Split |
Close |
| Expand all |
| Collapse all |
--- old/src/depot.py
+++ new/src/depot.py
1 1 #!/usr/bin/python2.4
2 2 #
3 3 # CDDL HEADER START
4 4 #
5 5 # The contents of this file are subject to the terms of the
6 6 # Common Development and Distribution License (the "License").
7 7 # You may not use this file except in compliance with the License.
8 8 #
9 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 # or http://www.opensolaris.org/os/licensing.
11 11 # See the License for the specific language governing permissions
12 12 # and limitations under the License.
13 13 #
14 14 # When distributing Covered Code, include this CDDL HEADER in each
15 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 # If applicable, add the following below this CDDL HEADER, with the
17 17 # fields enclosed by brackets "[]" replaced with your own identifying
18 18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 19 #
20 20 # CDDL HEADER END
21 21 #
22 22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 # Use is subject to license terms.
24 24 #
25 25
26 26 # pkg.depotd - package repository daemon
27 27
28 28 # XXX The prototype pkg.depotd combines both the version management server that
29 29 # answers to pkgsend(1) sessions and the HTTP file server that answers to the
30 30 # various GET operations that a pkg(1) client makes. This split is expected to
31 31 # be made more explicit, by constraining the pkg(1) operations such that they
32 32 # can be served as a typical HTTP/HTTPS session. Thus, pkg.depotd will reduce
33 33 # to a special purpose HTTP/HTTPS server explicitly for the version management
34 34 # operations, and must manipulate the various state files--catalogs, in
35 35 # particular--such that the pkg(1) pull client can operately accurately with
36 36 # only a basic HTTP/HTTPS server in place.
37 37
38 38 # XXX We should support simple "last-modified" operations via HEAD queries.
39 39
40 40 # XXX Although we pushed the evaluation of next-version, etc. to the pull
41 41 # client, we should probably provide a query API to do same on the server, for
42 42 # dumb clients (like a notification service).
43 43
44 44 # The default authority for the depot.
45 45 AUTH_DEFAULT = "opensolaris.org"
46 46 # The default repository path.
47 47 REPO_PATH_DEFAULT = "/var/pkg/repo"
48 48 # The default path for static and other web content.
49 49 CONTENT_PATH_DEFAULT = "/usr/share/lib/pkg"
50 50 # cherrypy has a max_request_body_size parameter that determines whether the
51 51 # server should abort requests with REQUEST_ENTITY_TOO_LARGE when the request
52 52 # body is larger than the specified size (in bytes). The maximum size supported
53 53 # by cherrypy is 2048 * 1024 * 1024 - 1 (just short of 2048MB), but the default
54 54 # here is purposefully conservative.
55 55 MAX_REQUEST_BODY_SIZE = 128 * 1024 * 1024
56 56 # The default port(s) to serve data from.
57 57 PORT_DEFAULT = 80
58 58 SSL_PORT_DEFAULT = 443
59 59 # The minimum number of threads allowed.
60 60 THREADS_MIN = 1
61 61 # The default number of threads to start.
62 62 THREADS_DEFAULT = 10
63 63 # The maximum number of threads that can be started.
64 64 THREADS_MAX = 100
65 65 # The default server socket timeout in seconds. We want this to be longer than
66 66 # the normal default of 10 seconds to accommodate clients with poor quality
67 67 # connections.
68 68 SOCKET_TIMEOUT_DEFAULT = 60
69 69 # Whether modify operations should be allowed.
70 70 READONLY_DEFAULT = False
71 71 # Whether the repository catalog should be rebuilt on startup.
72 72 REBUILD_DEFAULT = False
73 73 # Whether the indexes should be rebuilt
74 74 REINDEX_DEFAULT = False
75 75 # Not in mirror mode by default
76 76 MIRROR_DEFAULT = False
77 77
78 78 import getopt
79 79 import gettext
80 80 import locale
81 81 import logging
82 82 import os
83 83 import os.path
84 84 import OpenSSL.crypto as crypto
85 85 import subprocess
86 86 import sys
87 87 import tempfile
88 88 import urlparse
89 89
90 90 try:
91 91 import cherrypy
92 92 version = cherrypy.__version__.split('.')
93 93 if map(int, version) < [3, 1, 0]:
94 94 raise ImportError
95 95 elif map(int, version) >= [3, 2, 0]:
96 96 raise ImportError
97 97 except ImportError:
98 98 print >> sys.stderr, """cherrypy 3.1.0 or greater (but less than """ \
99 99 """3.2.0) is required to use this program."""
100 100 sys.exit(2)
101 101
102 102 import pkg.catalog as catalog
103 103 from pkg.misc import port_available, msg, emsg, setlocale
104 104 import pkg.portable.util as os_util
105 105 import pkg.search_errors as search_errors
106 106 import pkg.server.config as config
107 107 import pkg.server.depot as depot
108 108 import pkg.server.depotresponse as dr
109 109 import pkg.server.errors as errors
110 110 import pkg.server.repositoryconfig as rc
111 111
112 112 class LogSink(object):
113 113 """This is a dummy object that we can use to discard log entries
114 114 without relying on non-portable interfaces such as /dev/null."""
115 115
116 116 def write(self, *args, **kwargs):
117 117 """Discard the bits."""
118 118 pass
119 119
120 120 def flush(self, *args, **kwargs):
|
↓ open down ↓ |
120 lines elided |
↑ open up ↑ |
121 121 """Discard the bits."""
122 122 pass
123 123
124 124 def usage(text):
125 125 if text:
126 126 emsg(text)
127 127
128 128 print """\
129 129 Usage: /usr/lib/pkg.depotd [-d repo_dir] [-p port] [-s threads]
130 130 [-t socket_timeout] [--cfg-file] [--content-root] [--debug]
131 - [--log-access dest] [--log-errors dest] [--mirror] [--proxy-base url]
132 - [--readonly] [--rebuild] [--ssl-cert-file] [--ssl-dialog]
133 - [--ssl-key-file] [--writable-root dir]
131 + [--log-access dest] [--log-errors dest] [--mirror] [--nasty]
132 + [--proxy-base url] [--readonly] [--rebuild] [--ssl-cert-file]
133 + [--ssl-dialog] [--ssl-key-file] [--writable-root dir]
134 134
135 135 --cfg-file The pathname of the file from which to read and to
136 136 write configuration information.
137 137 --content-root The file system path to the directory containing the
138 138 the static and other web content used by the depot's
139 139 browser user interface. The default value is
140 140 '/usr/share/lib/pkg'.
141 141 --debug The name of a debug feature to enable; or a whitespace
142 142 or comma separated list of features to enable. Possible
143 143 values are: headers.
144 144 --log-access The destination for any access related information
145 145 logged by the depot process. Possible values are:
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
146 146 stderr, stdout, none, or an absolute pathname. The
147 147 default value is stdout if stdout is a tty; otherwise
148 148 the default value is none.
149 149 --log-errors The destination for any errors or other information
150 150 logged by the depot process. Possible values are:
151 151 stderr, stdout, none, or an absolute pathname. The
152 152 default value is stderr.
153 153 --mirror Package mirror mode; publishing and metadata operations
154 154 disallowed. Cannot be used with --readonly or
155 155 --rebuild.
156 + --nasty Instruct the server to misbehave. At random intervals
157 + it will time-out, send bad responses, hang up on
158 + clients, and generally be hostile. The option
159 + takes a value (1 to 100) for how nasty the server
160 + should be.
156 161 --proxy-base The url to use as the base for generating internal
157 162 redirects and content.
158 163 --readonly Read-only operation; modifying operations disallowed.
159 164 Cannot be used with --mirror or --rebuild.
160 165 --rebuild Re-build the catalog from pkgs in depot. Cannot be
161 166 used with --mirror or --readonly.
162 167 --ssl-cert-file The absolute pathname to a PEM-encoded Certificate file.
163 168 This option must be used with --ssl-key-file. Usage of
164 169 this option will cause the depot to only respond to SSL
165 170 requests on the provided port.
166 171 --ssl-dialog Specifies what method should be used to obtain the
167 172 passphrase needed to decrypt the file specified by
168 173 --ssl-key-file. Supported values are: builtin,
169 174 exec:/path/to/program, or smf:fmri. The default value
170 175 is builtin.
171 176 --ssl-key-file The absolute pathname to a PEM-encoded Private Key file.
172 177 This option must be used with --ssl-cert-file. Usage of
173 178 this option will cause the depot to only respond to SSL
174 179 requests on the provided port.
175 180 --writable-root The path to a directory to which the program has write
176 181 access. Used with --readonly to allow server to
177 182 create needed files, such as search indices, without
178 183 needing write access to the package information.
179 184 """
180 185 sys.exit(2)
181 186
182 187 class OptionError(Exception):
183 188 """Option exception. """
184 189
185 190 def __init__(self, *args):
186 191 Exception.__init__(self, *args)
187 192
188 193 if __name__ == "__main__":
189 194
190 195 setlocale(locale.LC_ALL, "")
191 196 gettext.install("pkg", "/usr/share/locale")
192 197
193 198 debug_features = {
194 199 "headers": False,
|
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
195 200 }
196 201 port = PORT_DEFAULT
197 202 port_provided = False
198 203 threads = THREADS_DEFAULT
199 204 socket_timeout = SOCKET_TIMEOUT_DEFAULT
200 205 readonly = READONLY_DEFAULT
201 206 rebuild = REBUILD_DEFAULT
202 207 reindex = REINDEX_DEFAULT
203 208 proxy_base = None
204 209 mirror = MIRROR_DEFAULT
210 + nasty = False
211 + nasty_value = 0
205 212 repo_config_file = None
206 213 ssl_cert_file = None
207 214 ssl_key_file = None
208 215 ssl_dialog = "builtin"
209 216 writable_root = None
210 217
211 218 if "PKG_REPO" in os.environ:
212 219 repo_path = os.environ["PKG_REPO"]
213 220 else:
214 221 repo_path = REPO_PATH_DEFAULT
215 222
216 223 try:
217 224 content_root = os.environ["PKG_DEPOT_CONTENT"]
218 225 except KeyError:
219 226 try:
220 227 content_root = os.path.join(os.environ['PKG_HOME'],
221 228 'share/lib/pkg')
222 229 except KeyError:
223 230 content_root = CONTENT_PATH_DEFAULT
224 231
225 232 # By default, if the destination for a particular log type is not
226 233 # specified, this is where we will send the output.
227 234 log_routes = {
228 235 "access": "none",
229 236 "errors": "stderr"
230 237 }
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
231 238 log_opts = ["--log-%s" % log_type for log_type in log_routes]
232 239
233 240 # If stdout is a tty, then send access output there by default instead
234 241 # of discarding it.
235 242 if os.isatty(sys.stdout.fileno()):
236 243 log_routes["access"] = "stdout"
237 244
238 245 opt = None
239 246 try:
240 247 long_opts = ["cfg-file=", "content-root=", "debug=", "mirror",
241 - "proxy-base=", "readonly", "rebuild", "refresh-index",
242 - "ssl-cert-file=", "ssl-dialog=", "ssl-key-file=",
243 - "writable-root="]
248 + "nasty=", "proxy-base=", "readonly", "rebuild",
249 + "refresh-index", "ssl-cert-file=", "ssl-dialog=",
250 + "ssl-key-file=", "writable-root="]
244 251 for opt in log_opts:
245 252 long_opts.append("%s=" % opt.lstrip('--'))
246 253 opts, pargs = getopt.getopt(sys.argv[1:], "d:np:s:t:",
247 254 long_opts)
248 255 for opt, arg in opts:
249 256 if opt == "-n":
250 257 sys.exit(0)
251 258 elif opt == "-d":
252 259 repo_path = arg
253 260 elif opt == "-p":
254 261 port = int(arg)
255 262 port_provided = True
256 263 elif opt == "-s":
257 264 threads = int(arg)
258 265 if threads < THREADS_MIN:
259 266 raise OptionError, \
260 267 "minimum value is %d" % THREADS_MIN
261 268 if threads > THREADS_MAX:
262 269 raise OptionError, \
263 270 "maximum value is %d" % THREADS_MAX
264 271 elif opt == "-t":
265 272 socket_timeout = int(arg)
266 273 elif opt == "--cfg-file":
267 274 repo_config_file = os.path.abspath(arg)
268 275 elif opt == "--content-root":
269 276 if arg == "":
270 277 raise OptionError, "You must specify " \
271 278 "a directory path."
272 279 content_root = arg
273 280 elif opt == "--debug":
274 281 if arg is None or arg == "":
275 282 raise OptionError, \
276 283 "A debug feature must be specified."
277 284
278 285 # A list of features can be specified using a
279 286 # "," or any whitespace character as separators.
280 287 if "," in arg:
281 288 features = arg.split(",")
282 289 else:
283 290 features = arg.split()
284 291
285 292 for f in features:
286 293 if f not in debug_features:
287 294 raise OptionError, \
288 295 "Invalid debug feature: " \
|
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
289 296 "%s." % f
290 297 debug_features[f] = True
291 298 elif opt in log_opts:
292 299 if arg is None or arg == "":
293 300 raise OptionError, \
294 301 "You must specify a log " \
295 302 "destination."
296 303 log_routes[opt.lstrip("--log-")] = arg
297 304 elif opt == "--mirror":
298 305 mirror = True
306 + elif opt == "--nasty":
307 + value_err = None
308 + try:
309 + nasty_value = int(arg)
310 + except ValueError, e:
311 + value_err = e
312 +
313 + if value_err or (nasty_value > 100 or
314 + nasty_value < 1):
315 + raise OptionError, "Invalid value " \
316 + "for nasty option.\n Please " \
317 + "choose a value between 1 and 100."
318 + nasty = True
299 319 elif opt == "--proxy-base":
300 320 # Attempt to decompose the url provided into
301 321 # its base parts. This is done so we can
302 322 # remove any scheme information since we
303 323 # don't need it.
304 324 scheme, netloc, path, params, query, \
305 325 fragment = urlparse.urlparse(arg,
306 326 "http", allow_fragments=0)
307 327
308 328 if not netloc:
309 329 raise OptionError, "Unable to " \
310 330 "determine the hostname from " \
311 331 "the provided URL; please use a " \
312 332 "fully qualified URL."
313 333
314 334 scheme = scheme.lower()
315 335 if scheme not in ("http", "https"):
316 336 raise OptionError, "Invalid URL; http " \
317 337 "and https are the only supported " \
318 338 "schemes."
319 339
320 340 # Rebuild the url with the sanitized components.
321 341 proxy_base = urlparse.urlunparse((scheme,
322 342 netloc, path, params, query, fragment))
323 343 elif opt == "--readonly":
324 344 readonly = True
325 345 elif opt == "--rebuild":
326 346 rebuild = True
327 347 elif opt == "--refresh-index":
328 348 # Note: This argument is for internal use
329 349 # only. It's used when pkg.depotd is reexecing
330 350 # itself and needs to know that's the case.
331 351 # This flag is purposefully omitted in usage.
332 352 # The supported way to forcefully reindex is to
333 353 # kill any pkg.depot using that directory,
334 354 # remove the index directory, and restart the
335 355 # pkg.depot process. The index will be rebuilt
336 356 # automatically on startup.
337 357 reindex = True
338 358 elif opt == "--ssl-cert-file":
339 359 if arg == "none":
340 360 continue
341 361
342 362 ssl_cert_file = arg
343 363 if not os.path.isabs(ssl_cert_file):
344 364 raise OptionError, "The path to " \
345 365 "the Certificate file must be " \
346 366 "absolute."
347 367 elif not os.path.exists(ssl_cert_file):
348 368 raise OptionError, "The specified " \
349 369 "file does not exist."
350 370 elif not os.path.isfile(ssl_cert_file):
351 371 raise OptionError, "The specified " \
352 372 "pathname is not a file."
353 373 elif opt == "--ssl-key-file":
354 374 if arg == "none":
355 375 continue
356 376
357 377 ssl_key_file = arg
358 378 if not os.path.isabs(ssl_key_file):
359 379 raise OptionError, "The path to " \
360 380 "the Private Key file must be " \
361 381 "absolute."
362 382 elif not os.path.exists(ssl_key_file):
363 383 raise OptionError, "The specified " \
364 384 "file does not exist."
365 385 elif not os.path.isfile(ssl_key_file):
366 386 raise OptionError, "The specified " \
367 387 "pathname is not a file."
368 388 elif opt == "--ssl-dialog":
369 389 if arg != "builtin" and not \
370 390 arg.startswith("exec:/") and not \
371 391 arg.startswith("smf:"):
372 392 raise OptionError, "Invalid value " \
373 393 "specified. Expected: builtin, " \
374 394 "exec:/path/to/program, or " \
375 395 "smf:fmri."
376 396
377 397 f = arg
378 398 if f.startswith("exec:"):
379 399 if os_util.get_canonical_os_type() != \
380 400 "unix":
381 401 # Don't allow a somewhat
382 402 # insecure authentication method
383 403 # on some platforms.
384 404 raise OptionError, "exec is " \
385 405 "not a supported dialog " \
386 406 "type for this operating " \
387 407 "system."
388 408
389 409 f = os.path.abspath(f.split(
390 410 "exec:")[1])
391 411
392 412 if not os.path.isfile(f):
393 413 raise OptionError, "Invalid " \
394 414 "file path specified for " \
395 415 "exec."
396 416
397 417 f = "exec:%s" % f
398 418
399 419 ssl_dialog = f
400 420 elif opt == "--writable-root":
401 421 if arg == "":
402 422 raise OptionError, "You must specify " \
403 423 "a directory path."
404 424 writable_root = arg
405 425 except getopt.GetoptError, _e:
406 426 usage("pkg.depotd: %s" % _e.msg)
407 427 except OptionError, _e:
408 428 usage("pkg.depotd: option: %s -- %s" % (opt, _e))
409 429 except (ArithmeticError, ValueError):
410 430 usage("pkg.depotd: illegal option value: %s specified " \
411 431 "for option: %s" % (arg, opt))
412 432
413 433 if rebuild and reindex:
414 434 usage("--refresh-index cannot be used with --rebuild")
415 435 if rebuild and (readonly or mirror):
416 436 usage("--readonly and --mirror cannot be used with --rebuild")
417 437 if reindex and mirror:
418 438 usage("--mirror cannot be used with --refresh-index")
419 439 if reindex and readonly and not writable_root:
420 440 usage("--readonly can only be used with --refresh-index if "
421 441 "--writable-root is used")
422 442
423 443 if (ssl_cert_file and not ssl_key_file) or (ssl_key_file and not
424 444 ssl_cert_file):
425 445 usage("The --ssl-cert-file and --ssl-key-file options must "
426 446 "must both be provided when using either option.")
427 447 elif ssl_cert_file and ssl_key_file and not port_provided:
428 448 # If they didn't already specify a particular port, use the
429 449 # default SSL port instead.
430 450 port = SSL_PORT_DEFAULT
431 451
432 452 # If the program is going to reindex, the port is irrelevant since
433 453 # the program will not bind to a port.
434 454 if not reindex:
435 455 available, msg = port_available(None, port)
|
↓ open down ↓ |
127 lines elided |
↑ open up ↑ |
436 456 if not available:
437 457 print "pkg.depotd: unable to bind to the specified " \
438 458 "port: %d. Reason: %s" % (port, msg)
439 459 sys.exit(1)
440 460 else:
441 461 # Not applicable for reindexing operations.
442 462 content_root = None
443 463
444 464 fork_allowed = not reindex
445 465
446 - scfg = config.SvrConfig(repo_path, content_root, AUTH_DEFAULT,
447 - auto_create=not readonly, fork_allowed=fork_allowed,
448 - writable_root=writable_root)
466 + if nasty:
467 + scfg = config.NastySvrConfig(repo_path, content_root,
468 + AUTH_DEFAULT, auto_create=not readonly,
469 + fork_allowed=fork_allowed, writable_root=writable_root)
470 + scfg.set_nasty(nasty_value)
471 + else:
472 + scfg = config.SvrConfig(repo_path, content_root, AUTH_DEFAULT,
473 + auto_create=not readonly, fork_allowed=fork_allowed,
474 + writable_root=writable_root)
449 475
450 476 if readonly:
451 477 scfg.set_read_only()
452 478
453 479 if mirror:
454 480 scfg.set_mirror()
455 481
482 +
456 483 try:
457 484 scfg.init_dirs()
458 485 except (errors.SvrConfigError, EnvironmentError), _e:
459 486 print "pkg.depotd: an error occurred while trying to " \
460 487 "initialize the depot repository directory " \
461 488 "structures:\n%s" % _e
462 489 sys.exit(1)
463 490
464 491 key_data = None
465 492 if not reindex and ssl_cert_file and ssl_key_file and \
466 493 ssl_dialog != "builtin":
467 494 cmdline = None
468 495 def get_ssl_passphrase(*ignored):
469 496 p = None
470 497 try:
471 498 p = subprocess.Popen(cmdline, shell=True,
472 499 stdout=subprocess.PIPE,
473 500 stderr=None)
474 501 p.wait()
475 502 except Exception, __e:
476 503 print "pkg.depotd: an error occurred while " \
477 504 "executing [%s]; unable to obtain the " \
478 505 "passphrase needed to decrypt the SSL" \
479 506 "private key file: %s" % (cmdline, __e)
480 507 sys.exit(1)
481 508 return p.stdout.read().strip("\n")
482 509
483 510 if ssl_dialog.startswith("exec:"):
484 511 cmdline = "%s %s %d" % (ssl_dialog.split("exec:")[1],
485 512 "''", port)
486 513 elif ssl_dialog.startswith("smf:"):
487 514 cmdline = "/usr/bin/svcprop -p " \
488 515 "pkg_secure/ssl_key_passphrase %s" % (
489 516 ssl_dialog.split("smf:")[1])
490 517
491 518 # The key file requires decryption, but the user has requested
492 519 # exec-based authentication, so it will have to be decoded first
493 520 # to an un-named temporary file.
494 521 try:
495 522 key_file = file(ssl_key_file, "rb")
496 523 pkey = crypto.load_privatekey(crypto.FILETYPE_PEM,
497 524 key_file.read(), get_ssl_passphrase)
498 525
499 526 key_data = tempfile.TemporaryFile()
500 527 key_data.write(crypto.dump_privatekey(
501 528 crypto.FILETYPE_PEM, pkey))
502 529 key_data.seek(0)
503 530 except EnvironmentError, _e:
504 531 print "pkg.depotd: unable to read the SSL private " \
505 532 "key file: %s" % _e
506 533 sys.exit(1)
507 534 except crypto.Error, _e:
508 535 print "pkg.depotd: authentication or cryptography " \
509 536 "failure while attempting to decode\nthe SSL " \
510 537 "private key file: %s" % _e
511 538 sys.exit(1)
512 539 else:
513 540 # Redirect the server to the decrypted key file.
514 541 ssl_key_file = "/dev/fd/%d" % key_data.fileno()
515 542
516 543 # Setup our global configuration.
517 544 gconf = {
518 545 "checker.on": True,
519 546 "environment": "production",
520 547 "log.screen": False,
521 548 "server.max_request_body_size": MAX_REQUEST_BODY_SIZE,
522 549 "server.shutdown_timeout": 0,
523 550 "server.socket_host": "0.0.0.0",
524 551 "server.socket_port": port,
525 552 "server.socket_timeout": socket_timeout,
526 553 "server.ssl_certificate": ssl_cert_file,
527 554 "server.ssl_private_key": ssl_key_file,
528 555 "server.thread_pool": threads,
529 556 "tools.log_headers.on": True,
530 557 "tools.encode.on": True
531 558 }
532 559
533 560 if debug_features["headers"]:
534 561 # Despite its name, this only logs headers when there is an
535 562 # error; it's redundant with the debug feature enabled.
536 563 gconf["tools.log_headers.on"] = False
537 564
538 565 # Causes the headers of every request to be logged to the error
539 566 # log; even if an exception occurs.
540 567 gconf["tools.log_headers_always.on"] = True
541 568 cherrypy.tools.log_headers_always = cherrypy.Tool(
542 569 "on_start_resource",
543 570 cherrypy.lib.cptools.log_request_headers)
544 571
545 572 log_type_map = {
546 573 "errors": {
547 574 "param": "log.error_file",
548 575 "attr": "error_log"
549 576 },
550 577 "access": {
551 578 "param": "log.access_file",
552 579 "attr": "access_log"
553 580 }
554 581 }
555 582
556 583 for log_type in log_type_map:
557 584 dest = log_routes[log_type]
558 585 if dest in ("stdout", "stderr", "none"):
559 586 if dest == "none":
560 587 h = logging.StreamHandler(LogSink())
561 588 else:
562 589 h = logging.StreamHandler(eval("sys.%s" % \
563 590 dest))
564 591
565 592 h.setLevel(logging.DEBUG)
566 593 h.setFormatter(cherrypy._cplogging.logfmt)
567 594 log_obj = eval("cherrypy.log.%s" % \
568 595 log_type_map[log_type]["attr"])
569 596 log_obj.addHandler(h)
570 597 # Since we've replaced cherrypy's log handler with our
571 598 # own, we don't want the output directed to a file.
572 599 dest = ""
573 600
574 601 gconf[log_type_map[log_type]["param"]] = dest
575 602
576 603 cherrypy.config.update(gconf)
577 604
578 605 # Now that our logging, etc. has been setup, it's safe to perform any
579 606 # remaining preparation.
580 607 if reindex:
581 608 try:
582 609 scfg.acquire_catalog(rebuild=False, verbose=True)
583 610 except (search_errors.IndexingException,
584 611 catalog.CatalogPermissionsException,
585 612 errors.SvrConfigError), e:
586 613 cherrypy.log(str(e), "INDEX")
587 614 sys.exit(1)
588 615 sys.exit(0)
589 616
590 617 # Now build our site configuration.
591 618 conf = {
592 619 "/": {
593 620 # We have to override cherrypy's default response_class so that
594 621 # we have access to the write() callable to stream data
595 622 # directly to the client.
596 623 "wsgi.response_class": dr.DepotResponse,
597 624 },
598 625 "/robots.txt": {
599 626 "tools.staticfile.on": True,
600 627 "tools.staticfile.filename": os.path.join(scfg.web_root,
601 628 "robots.txt")
602 629 },
603 630 }
604 631
605 632 if proxy_base:
606 633 # This changes the base URL for our server, and is primarily
607 634 # intended to allow our depot process to operate behind Apache
608 635 # or some other webserver process.
609 636 #
610 637 # Visit the following URL for more information:
611 638 # http://cherrypy.org/wiki/BuiltinTools#tools.proxy
612 639 proxy_conf = {
613 640 "tools.proxy.on": True,
614 641 "tools.proxy.local": "",
615 642 "tools.proxy.base": proxy_base
616 643 }
617 644
618 645 # Now merge or add our proxy configuration information into the
619 646 # existing configuration.
620 647 for entry in proxy_conf:
|
↓ open down ↓ |
155 lines elided |
↑ open up ↑ |
621 648 conf["/"][entry] = proxy_conf[entry]
622 649
623 650 scfg.acquire_in_flight()
624 651 try:
625 652 scfg.acquire_catalog(rebuild=rebuild, verbose=True)
626 653 except (catalog.CatalogPermissionsException, errors.SvrConfigError), _e:
627 654 emsg("pkg.depotd: %s" % _e)
628 655 sys.exit(1)
629 656
630 657 try:
631 - root = cherrypy.Application(depot.DepotHTTP(scfg,
632 - repo_config_file))
658 + if nasty:
659 + root = cherrypy.Application(depot.NastyDepotHTTP(scfg,
660 + repo_config_file))
661 + else:
662 + root = cherrypy.Application(depot.DepotHTTP(scfg,
663 + repo_config_file))
633 664 except rc.InvalidAttributeValueError, _e:
634 665 emsg("pkg.depotd: repository.conf error: %s" % _e)
635 666 sys.exit(1)
636 667
637 668 try:
638 669 cherrypy.quickstart(root, config=conf)
639 670 except Exception, _e:
640 671 emsg("pkg.depotd: unknown error starting depot server, " \
641 672 "illegal option value specified?")
642 673 emsg(_e)
643 674 sys.exit(1)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX