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 3133 """ 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 s48 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:" 7678 """ 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 9395 """ 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 120122 """ 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')713228 """ 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 242244 """ 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 256258 """ 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 266268 """ 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 url301303 """ 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()308310 """ 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 331333 """ 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()338340 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 server352354 """ 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)365367 """ 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 387389 """ 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 400402 """ 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 gopts420 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 devlist439 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)465467 """ 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 492494 """ 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 devices546547 - 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 jobStatus593594 - 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 result624625 - 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 zendiscCmd639 642644 """ 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 result661 662663 - 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 0688 689690 - 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 result715786 787 InitializeClass(PerformanceConf) 788717 self._renderurl = renderurl718720 """ 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 renderurl730732 """ 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 ''749751 """ 752 Should the render request be proxied by zenoss/zope 753 """ 754 return self._renderurl.startswith('proxy')755757 # 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)765767 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
Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1.1812 on Mon Jul 30 17:11:29 2012 | http://epydoc.sourceforge.net |