| Trees | Indices | Help |
|
|---|
|
|
1 #! /usr/bin/env python
2 ##############################################################################
3 #
4 # Copyright (C) Zenoss, Inc. 2006-2009, all rights reserved.
5 #
6 # This content is made available according to terms specified in
7 # License.zenoss under the directory where your Zenoss product is installed.
8 #
9 ##############################################################################
10
11
12 __doc__ = """PerformanceConf
13 The configuration object for Performance servers
14 """
15
16 import os
17 import zlib
18 import socket
19 from urllib import urlencode
20 from ipaddr import IPAddress
21 import logging
22 log = logging.getLogger('zen.PerformanceConf')
23
24 from Products.ZenUtils.IpUtil import ipwrap
25
26 try:
27 from base64 import urlsafe_b64encode
28 raise ImportError
29 except ImportError:
30
31
33 """
34 Encode a string so that it's okay to be used in an URL
35
36 @param s: possibly unsafe string passed in by the user
37 @type s: string
38 @return: sanitized, url-safe version of the string
39 @rtype: string
40 """
41
42 import base64
43 s = base64.encodestring(s)
44 s = s.replace('+', '-')
45 s = s.replace('/', '_')
46 s = s.replace('\n', '')
47 return s
48
49
50 import xmlrpclib
51
52 from AccessControl import ClassSecurityInfo
53 from AccessControl import Permissions as permissions
54 from Globals import DTMLFile
55 from Globals import InitializeClass
56 from Monitor import Monitor
57 from Products.Jobber.jobs import SubprocessJob
58 from Products.ZenRelations.RelSchema import ToMany, ToOne
59 from Products.ZenUtils.Utils import basicAuthUrl, zenPath, binPath
60 from Products.ZenUtils.Utils import unused
61 from Products.ZenUtils.Utils import isXmlRpc
62 from Products.ZenUtils.Utils import executeCommand
63 from Products.ZenModel.ZDeviceLoader import DeviceCreationJob
64 from Products.ZenWidgets import messaging
65 from Products.ZenMessaging.audit import audit
66 from StatusColor import StatusColor
67
68 PERF_ROOT = None
69
70 """
71 Prefix for renderurl if zenoss is running a reverse proxy on the master. Prefix will be stripped when appropriate and
72 requests for data will be made to the proxy server when appropriate. Render url should be of the form "rev_proxy:/<path>" eg:
73 "rev_proxy:/mypath" where /mypath should be proxied to an appropriate zenrender/renderserver by the installed proxy server
74 """
75 REVERSE_PROXY = "rev_proxy:"
76
78 """
79 Return the base directory where RRD performance files are kept.
80
81 @param target: path to performance file
82 @type target: string
83 @return: sanitized path to performance file
84 @rtype: string
85 """
86 global PERF_ROOT
87 if PERF_ROOT is None:
88 PERF_ROOT = zenPath('perf')
89 if target.startswith('/'):
90 target = target[1:]
91 return os.path.join(PERF_ROOT, target)
92
93
95 """
96 Make a device class
97
98 @param context: Where you are in the Zope acquisition path
99 @type context: Zope context object
100 @param id: unique identifier
101 @type id: string
102 @param title: user readable label (unused)
103 @type title: string
104 @param REQUEST: Zope REQUEST object
105 @type REQUEST: Zope REQUEST object
106 @return:
107 @rtype:
108 """
109 unused(title)
110 dc = PerformanceConf(id)
111 context._setObject(id, dc)
112
113 if REQUEST is not None:
114 REQUEST['RESPONSE'].redirect(context.absolute_url()
115 + '/manage_main')
116
117
118 addPerformanceConf = DTMLFile('dtml/addPerformanceConf', globals())
119
120
122 """
123 Configuration for Performance servers
124 """
125 portal_type = meta_type = 'PerformanceConf'
126
127 monitorRootName = 'Performance'
128
129 security = ClassSecurityInfo()
130 security.setDefaultAccess('allow')
131
132 eventlogCycleInterval = 60
133 perfsnmpCycleInterval = 300
134 processCycleInterval = 180
135 statusCycleInterval = 60
136 winCycleInterval = 60
137 wmibatchSize = 10
138 wmiqueryTimeout = 100
139 configCycleInterval = 6 * 60
140
141 zenProcessParallelJobs = 10
142
143 pingTimeOut = 1.5
144 pingTries = 2
145 pingChunk = 75
146 pingCycleInterval = 60
147 maxPingFailures = 1440
148
149 modelerCycleInterval = 720
150
151 renderurl = '/zport/RenderServer'
152 renderuser = ''
153 renderpass = ''
154
155 discoveryNetworks = ()
156
157 # make the default rrdfile size smaller
158 # we need the space to live within the disk cache
159 defaultRRDCreateCommand = (
160 'RRA:AVERAGE:0.5:1:600', # every 5 mins for 2 days
161 'RRA:AVERAGE:0.5:6:600', # every 30 mins for 12 days
162 'RRA:AVERAGE:0.5:24:600', # every 2 hours for 50 days
163 'RRA:AVERAGE:0.5:288:600', # every day for 600 days
164 'RRA:MAX:0.5:6:600',
165 'RRA:MAX:0.5:24:600',
166 'RRA:MAX:0.5:288:600',
167 )
168
169 _properties = (
170 {'id': 'eventlogCycleInterval', 'type': 'int', 'mode': 'w'},
171 {'id': 'perfsnmpCycleInterval', 'type': 'int', 'mode': 'w'},
172 {'id': 'processCycleInterval', 'type': 'int', 'mode': 'w'},
173 {'id': 'statusCycleInterval', 'type': 'int', 'mode': 'w'},
174 {'id': 'winCycleInterval', 'type': 'int', 'mode': 'w'},
175 {'id': 'wmibatchSize', 'type': 'int', 'mode': 'w',
176 'description':"Number of data objects to retrieve in a single WMI query",},
177 {'id': 'wmiqueryTimeout', 'type': 'int', 'mode': 'w',
178 'description':"Number of milliseconds to wait for WMI query to respond",},
179 {'id': 'configCycleInterval', 'type': 'int', 'mode': 'w'},
180 {'id': 'renderurl', 'type': 'string', 'mode': 'w'},
181 {'id': 'renderuser', 'type': 'string', 'mode': 'w'},
182 {'id': 'renderpass', 'type': 'string', 'mode': 'w'},
183 {'id': 'defaultRRDCreateCommand', 'type': 'lines', 'mode': 'w'
184 },
185 {'id': 'zenProcessParallelJobs', 'type': 'int', 'mode': 'w'},
186 {'id': 'pingTimeOut', 'type': 'float', 'mode': 'w'},
187 {'id': 'pingTries', 'type': 'int', 'mode': 'w'},
188 {'id': 'pingChunk', 'type': 'int', 'mode': 'w'},
189 {'id': 'pingCycleInterval', 'type': 'int', 'mode': 'w'},
190 {'id': 'maxPingFailures', 'type': 'int', 'mode': 'w'},
191 {'id': 'modelerCycleInterval', 'type': 'int', 'mode': 'w'},
192 {'id': 'discoveryNetworks', 'type': 'lines', 'mode': 'w'},
193 )
194
195 _relations = Monitor._relations + (
196 ("devices", ToMany(ToOne,"Products.ZenModel.Device","perfServer")),
197 )
198
199 # Screen action bindings (and tab definitions)
200 factory_type_information = (
201 {
202 'immediate_view' : 'viewPerformanceConfOverview',
203 'actions' :
204 (
205 { 'id' : 'overview'
206 , 'name' : 'Overview'
207 , 'action' : 'viewPerformanceConfOverview'
208 , 'permissions' : (
209 permissions.view, )
210 },
211 { 'id' : 'edit'
212 , 'name' : 'Edit'
213 , 'action' : 'editPerformanceConf'
214 , 'permissions' : ("Manage DMD",)
215 },
216 { 'id' : 'performance'
217 , 'name' : 'Performance'
218 , 'action' : 'viewDaemonPerformance'
219 , 'permissions' : (permissions.view,)
220 },
221 )
222 },
223 )
224
225
226 security.declareProtected('View', 'getDefaultRRDCreateCommand')
228 """
229 Get the default RRD Create Command, as a string.
230 For example:
231 '''RRA:AVERAGE:0.5:1:600
232 RRA:AVERAGE:0.5:6:600
233 RRA:AVERAGE:0.5:24:600
234 RRA:AVERAGE:0.5:288:600
235 RRA:MAX:0.5:288:600'''
236
237 @return: RRD create command
238 @rtype: string
239 """
240 return '\n'.join(self.defaultRRDCreateCommand)
241
242
244 """
245 Return the object given the name
246
247 @param deviceName: Name of a device
248 @type deviceName: string
249 @return: device corresponding to the name, or None
250 @rtype: device object
251 """
252 brains = self.dmd.Devices._findDevice(deviceName)
253 if brains:
254 return brains[0].getObject()
255
256
258 """
259 Get the root of the Network object in the DMD
260
261 @return: base DMD Network object
262 @rtype: Network object
263 """
264 return self.dmd.Networks.getNetworkRoot(version)
265
266
268 """
269 Return an URL for the given graph options and date range
270
271 @param gopts: graph options
272 @type gopts: string
273 @param drange: time range to use
274 @type drange: string
275 @return: URL to a graphic
276 @rtype: string
277 """
278 newOpts = []
279 width = 0
280 for o in gopts:
281 if o.startswith('--width'):
282 width = o.split('=')[1].strip()
283 continue
284 newOpts.append(o)
285
286 encodedOpts = urlsafe_b64encode(
287 zlib.compress('|'.join(newOpts), 9))
288 params = {
289 'gopts': encodedOpts,
290 'drange': drange,
291 'width': width,
292 }
293
294 url = self._getSanitizedRenderURL()
295 if RenderURLUtil(self.renderurl).proxiedByZenoss():
296 params['remoteHost'] = self.getRemoteRenderUrl()
297 url = '/zport/RenderServer'
298
299 url = '%s/render?%s' % (url, urlencode(params),)
300 return url
301
303 """
304 remove any keywords/directives from renderurl.
305 example is "proxy://host:8091" is changed to "http://host:8091"
306 """
307 return RenderURLUtil(self.renderurl).getSanitizedRenderURL()
308
310 """
311 Set the full path of the target and send to view
312
313 @param context: Where you are in the Zope acquisition path
314 @type context: Zope context object
315 @param targetpath: device path of performance metric
316 @type targetpath: string
317 @param targettype: unused
318 @type targettype: string
319 @param view: view object
320 @type view: Zope object
321 @param drange: date range
322 @type drange: string
323 @return: URL to graph
324 @rtype: string
325 """
326 unused(targettype)
327 targetpath = performancePath(targetpath)
328 gopts = view.getGraphCmds(context, targetpath)
329 return self.buildGraphUrlFromCommands(gopts, drange)
330
331
333 """
334 return the full render url with http protocol prepended if the renderserver is remote.
335 Return empty string otherwise
336 """
337 return RenderURLUtil(self.renderurl).getRemoteRenderUrl()
338
340 if self.getRemoteRenderUrl():
341 renderurl = self.getRemoteRenderUrl()
342 # Going through the hub or directly to zenrender
343 log.info("Remote renderserver at %s", renderurl)
344 url = basicAuthUrl(str(self.renderuser),
345 str(self.renderpass), renderurl)
346 server = xmlrpclib.Server(url, allow_none=allow_none)
347 else:
348 if not self.renderurl:
349 raise KeyError("No render URL is defined")
350 server = self.getObjByPath(self.renderurl)
351 return server
352
354 """
355 Fill out full path for custom gopts and call to server
356
357 @param gopts: graph options
358 @type gopts: string
359 @return: URL
360 @rtype: string
361 """
362 gopts = self._fullPerformancePath(gopts)
363 server = self._get_render_server()
364 return server.summary(gopts)
365
367 """
368 Return values
369
370 @param paths: paths to performance metrics
371 @type paths: list
372 @param cf: RRD CF
373 @type cf: string
374 @param resolution: resolution
375 @type resolution: string
376 @param start: start time
377 @type start: string
378 @param end: end time
379 @type end: string
380 @return: values
381 @rtype: list
382 """
383 server = self._get_render_server(allow_none=True)
384 return server.fetchValues(map(performancePath, paths), cf,
385 resolution, start, end)
386
387
389 """
390 Fill out full path and call to server
391
392 @param paths: paths to performance metrics
393 @type paths: list
394 @return: values
395 @rtype: list
396 """
397 server = self._get_render_server()
398 return server.currentValues(map(performancePath, paths))
399
400
402 """
403 Add full path to a list of custom graph options
404
405 @param gopts: graph options
406 @type gopts: string
407 @return: full path + graph options
408 @rtype: string
409 """
410 for i in range(len(gopts)):
411 opt = gopts[i]
412 if opt.find('DEF') == 0:
413 opt = opt.split(':')
414 (var, file) = opt[1].split('=')
415 file = performancePath(file)
416 opt[1] = '%s=%s' % (var, file)
417 opt = ':'.join(opt)
418 gopts[i] = opt
419 return gopts
420
421
422 security.declareProtected('View', 'performanceDeviceList')
424 """
425 Return a list of URLs that point to our managed devices
426
427 @param force: unused
428 @type force: boolean
429 @return: list of device objects
430 @rtype: list
431 """
432 unused(force)
433 devlist = []
434 for dev in self.devices():
435 dev = dev.primaryAq()
436 if not dev.pastSnmpMaxFailures() and dev.monitorDevice():
437 devlist.append(dev.getPrimaryUrlPath(full=True))
438 return devlist
439
440
441 security.declareProtected('View', 'performanceDataSources')
443 """
444 Return a string that has all the definitions for the performance DS's.
445
446 @return: list of Data Sources
447 @rtype: string
448 """
449 dses = []
450 oidtmpl = 'OID %s %s'
451 dstmpl = """datasource %s
452 rrd-ds-type = %s
453 ds-source = snmp://%%snmp%%/%s%s
454 """
455 rrdconfig = self.getDmdRoot('Devices').rrdconfig
456 for ds in rrdconfig.objectValues(spec='RRDDataSource'):
457 if ds.isrow:
458 inst = '.%inst%'
459 else:
460 inst = ''
461 dses.append(oidtmpl % (ds.getName(), ds.oid))
462 dses.append(dstmpl % (ds.getName(), ds.rrdtype,
463 ds.getName(), inst))
464 return '\n'.join(dses)
465
467 """
468 Remove RRD performance data files
469
470 @param device: Name of a device or entry in DMD
471 @type device: string
472 @param datasource: datasource name
473 @type datasource: string
474 @param datapoint: datapoint name
475 @type datapoint: string
476 """
477 remoteUrl = None
478 renderurl = self.getRemoteRenderUrl() or self._getSanitizedRenderURL()
479 if renderurl.startswith('http'):
480 if datapoint:
481 remoteUrl = '%s/deleteRRDFiles?device=%s&datapoint=%s' % (
482 renderurl, device, datapoint)
483 elif datasource:
484 remoteUrl = '%s/deleteRRDFiles?device=%s&datasource=%s' % (
485 renderurl, device, datasource)
486 else:
487 remoteUrl = '%s/deleteRRDFiles?device=%s' % (
488 renderurl, device)
489 rs = self.getDmd().getParentNode().RenderServer
490 rs.deleteRRDFiles(device, datasource, datapoint, remoteUrl)
491
492
494 """
495 Provide a method to set performance monitor from any organizer
496
497 @param performanceMonitor: DMD object that collects from a device
498 @type performanceMonitor: DMD object
499 @param deviceNames: list of device names
500 @type deviceNames: list
501 @param REQUEST: Zope REQUEST object
502 @type REQUEST: Zope REQUEST object
503 """
504 if not performanceMonitor:
505 if REQUEST:
506 messaging.IMessageSender(self).sendToBrowser('Error',
507 'No monitor was selected.',
508 priority=messaging.WARNING)
509 return self.callZenScreen(REQUEST)
510 if deviceNames is None:
511 if REQUEST:
512 messaging.IMessageSender(self).sendToBrowser('Error',
513 'No devices were selected.',
514 priority=messaging.WARNING)
515 return self.callZenScreen(REQUEST)
516 for devName in deviceNames:
517 dev = self.devices._getOb(devName)
518 dev = dev.primaryAq()
519 dev.setPerformanceMonitor(performanceMonitor)
520 if REQUEST:
521 audit('UI.Device.ChangeCollector', dev, collector=performanceMonitor)
522 if REQUEST:
523 messaging.IMessageSender(self).sendToBrowser('Monitor Set',
524 'Performance monitor was set to %s.'
525 % performanceMonitor)
526 if REQUEST.has_key('oneKeyValueSoInstanceIsntEmptyAndEvalToFalse'):
527 return REQUEST['message']
528 else:
529 return self.callZenScreen(REQUEST)
530
531
532 security.declareProtected('View', 'getPingDevices')
534 """
535 Return devices associated with this monitor configuration.
536
537 @return: list of devices for this monitor
538 @rtype: list
539 """
540 devices = []
541 for dev in self.devices.objectValuesAll():
542 dev = dev.primaryAq()
543 if dev.monitorDevice() and not dev.zPingMonitorIgnore:
544 devices.append(dev)
545 return devices
546
547 - def addDeviceCreationJob(self, deviceName, devicePath, title=None,
548 discoverProto="none", manageIp="",
549 performanceMonitor='localhost',
550 rackSlot=0, productionState=1000, comments="",
551 hwManufacturer="", hwProductName="",
552 osManufacturer="", osProductName="", priority = 3,
553 locationPath="", systemPaths=[], groupPaths=[],
554 tag="", serialNumber="", zProperties={}):
555
556 # Check to see if we got passed in an IPv6 address
557 try:
558 IPAddress(deviceName)
559 if not title:
560 title = deviceName
561 deviceName = ipwrap(deviceName)
562 except ValueError:
563 pass
564
565 zendiscCmd = self._getZenDiscCommand(deviceName, devicePath,
566 performanceMonitor, productionState)
567
568 jobStatus = self.dmd.JobManager.addJob(DeviceCreationJob,
569 description="Add device %s" % deviceName,
570 kwargs=dict(
571 deviceName=deviceName,
572 devicePath=devicePath,
573 title=title,
574 discoverProto=discoverProto,
575 manageIp=manageIp,
576 performanceMonitor=performanceMonitor,
577 rackSlot=rackSlot,
578 productionState=productionState,
579 comments=comments,
580 hwManufacturer=hwManufacturer,
581 hwProductName=hwProductName,
582 osManufacturer=osManufacturer,
583 osProductName=osProductName,
584 priority=priority,
585 tag=tag,
586 serialNumber=serialNumber,
587 locationPath=locationPath,
588 systemPaths=systemPaths,
589 groupPaths=groupPaths,
590 zProperties=zProperties,
591 zendiscCmd=zendiscCmd))
592 return jobStatus
593
594 - def _executeZenDiscCommand(self, deviceName, devicePath= "/Discovered",
595 performanceMonitor="localhost", productionState=1000,
596 background=False, REQUEST=None):
597 """
598 Execute zendisc on the new device and return result
599
600 @param deviceName: Name of a device
601 @type deviceName: string
602 @param devicePath: DMD path to create the new device in
603 @type devicePath: string
604 @param performanceMonitor: DMD object that collects from a device
605 @type performanceMonitor: DMD object
606 @param background: should command be scheduled job?
607 @type background: boolean
608 @param REQUEST: Zope REQUEST object
609 @type REQUEST: Zope REQUEST object
610 @return:
611 @rtype:
612 """
613 zendiscCmd = self._getZenDiscCommand(deviceName, devicePath,
614 performanceMonitor,
615 productionState, REQUEST)
616 if background:
617 log.info('queued job: %s', " ".join(zendiscCmd))
618 result = self.dmd.JobManager.addJob(SubprocessJob,
619 description="Discover and model device %s" % deviceName,
620 args=(zendiscCmd,))
621 else:
622 result = executeCommand(zendiscCmd, REQUEST)
623 return result
624
625 - def _getZenDiscCommand(self, deviceName, devicePath,
626 performanceMonitor, productionState, REQUEST=None):
627
628 zm = binPath('zendisc')
629 zendiscCmd = [zm]
630 zendiscOptions = ['run', '--now','-d', deviceName,
631 '--monitor', performanceMonitor,
632 '--deviceclass', devicePath,
633 '--prod_state', str(productionState)]
634 if REQUEST:
635 zendiscOptions.append("--weblog")
636 zendiscCmd.extend(zendiscOptions)
637 log.info('local zendiscCmd is "%s"' % ' '.join(zendiscCmd))
638 return zendiscCmd
639
642
644 """
645 Executes the collector based daemon command.
646
647 @param command: the collector daemon to run, should not include path
648 @type command: string
649 @param args: list of arguments for the command
650 @type args: list of strings
651 @param REQUEST: Zope REQUEST object
652 @type REQUEST: Zope REQUEST object
653 @return: result of the command
654 @rtype: string
655 """
656 cmd = binPath(command)
657 daemonCmd = [cmd]
658 daemonCmd.extend(args)
659 result = executeCommand(daemonCmd, REQUEST)
660 return result
661
662
663 - def collectDevice(self, device=None, setlog=True, REQUEST=None,
664 generateEvents=False, background=False, write=None):
665 """
666 Collect the configuration of this device AKA Model Device
667
668 @permission: ZEN_MANAGE_DEVICE
669 @param device: Name of a device or entry in DMD
670 @type device: string
671 @param setlog: If true, set up the output log of this process
672 @type setlog: boolean
673 @param REQUEST: Zope REQUEST object
674 @type REQUEST: Zope REQUEST object
675 @param generateEvents: unused
676 @type generateEvents: string
677 """
678 xmlrpc = isXmlRpc(REQUEST)
679 zenmodelerOpts = ['run', '--now', '--monitor', self.id, '-d', device.id]
680 result = self._executeZenModelerCommand(zenmodelerOpts, background,
681 REQUEST, write)
682 if result and xmlrpc:
683 return result
684 log.info('configuration collected')
685
686 if xmlrpc:
687 return 0
688
689
690 - def _executeZenModelerCommand(self, zenmodelerOpts, background=False,
691 REQUEST=None, write=None):
692 """
693 Execute zenmodeler and return result
694
695 @param zenmodelerOpts: zenmodeler command-line options
696 @type zenmodelerOpts: string
697 @param REQUEST: Zope REQUEST object
698 @type REQUEST: Zope REQUEST object
699 @return: results of command
700 @rtype: string
701 """
702 zm = binPath('zenmodeler')
703 zenmodelerCmd = [zm]
704 zenmodelerCmd.extend(zenmodelerOpts)
705 if background:
706 log.info('queued job: %s', " ".join(zenmodelerCmd))
707 result = self.dmd.JobManager.addJob(SubprocessJob,
708 description="Run zenmodeler %s" % ' '.join(zenmodelerOpts),
709 args=(zenmodelerCmd,))
710 else:
711 result = executeCommand(zenmodelerCmd, REQUEST, write)
712 return result
713
715
717 self._renderurl = renderurl
718
720 """
721 remove any keywords/directives from renderurl.
722 example is "proxy://host:8091" is changed to "http://host:8091"
723 """
724 renderurl = self._renderurl
725 if renderurl.startswith('proxy'):
726 renderurl = renderurl.replace('proxy', 'http')
727 elif renderurl.startswith(REVERSE_PROXY):
728 renderurl = renderurl.replace(REVERSE_PROXY, '', 1)
729 return renderurl
730
732 """
733 return the full render url with http protocol prepended if the renderserver is remote.
734 Return empty string otherwise
735 """
736 renderurl = str(self._renderurl)
737 if renderurl.startswith('proxy'):
738 renderurl = renderurl.replace('proxy', 'http')
739 elif renderurl.startswith(REVERSE_PROXY):
740 renderurl = self._get_reverseproxy_renderurl()
741 else:
742 # lookup utilities from zenpacks
743 if renderurl.startswith('/remote-collector/'):
744 renderurl = self._get_reverseproxy_renderurl(force=True)
745
746 if renderurl.lower().startswith('http://'):
747 return renderurl
748 return ''
749
751 """
752 Should the render request be proxied by zenoss/zope
753 """
754 return self._renderurl.startswith('proxy')
755
757 # DistributedCollector + WebScale scenario
758 renderurl = self._renderurl
759 if not force and not renderurl.startswith(REVERSE_PROXY):
760 raise Exception("Renderurl, %s, should start with %s to be proxied", renderurl, REVERSE_PROXY)
761 kwargs = dict(fqdn=socket.getfqdn(),
762 port=self._get_reverseproxy_port(),
763 path=str(self.getSanitizedRenderURL()).strip("/") + "/")
764 return 'http://{fqdn}:{port}/{path}'.format(**kwargs)
765
767 use_ssl = False
768 http_port = 8080
769 ssl_port = 443
770 conf_path = zenPath("etc", "zenwebserver.conf")
771 if not os.path.exists(conf_path):
772 return http_port
773 with open(conf_path) as file_:
774 for line in (l.strip() for l in file_):
775 if line and not line.startswith('#'):
776 key, val = line.split(' ', 1)
777 if key == "useSSL":
778 use_ssl = val.lower() == 'true'
779 elif key == "httpPort":
780 http_port = int(val.strip())
781 elif key == "sslPort":
782 ssl_port = int(val.strip())
783 if use_ssl:
784 return ssl_port
785 return http_port
786
787 InitializeClass(PerformanceConf)
788
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1.1812 on Mon Jul 30 17:11:29 2012 | http://epydoc.sourceforge.net |