Removing unused mongo mms utils and configs.

This commit is contained in:
Samuel Clay 2022-05-10 20:53:56 -04:00
parent 30898df3e5
commit 5dba6549ef
34 changed files with 1 additions and 2111 deletions

1
.gitignore vendored
View file

@ -41,7 +41,6 @@ media/css/circular
config/settings
config/secrets
templates/maintenance_on.html
vendor/mms-agent/settings.py
apps/social/spam.py
venv*
backup

View file

@ -86,7 +86,7 @@ pyasn1==0.4.8
pycparser==2.20
pyflakes==2.2.0
PyJWT==1.7.1
pymongo>=3,<3.9
pymongo>=3,<4
PyMySQL==0.10.1
pynliner==0.8.0
pyOpenSSL==20.0.1

View file

@ -1,196 +0,0 @@
(C) Copyright 2012, 10gen
10gen MongoDB Monitoring Service (MMS) - Agent
=============
For the complete MMS documentation, see: https://mms.10gen.com/help/
The MMS agent polls your MongoDB instance(s) once per minute and relays statistics to 10gen.
New hosts are added by entering them on this page (click the plus/+ button on the top of the page) - https://mms.10gen.com/host/list
If you have a replica set, you only need to enter one host and the agent will discover the rest of the nodes in the group/cluster.
If you have a shard cluster, you only need to enter one mongos host and the agent will discover the rest of the nodes in the cluster.
Only one MMS agent is active at a time, the others are simply hot-standys.
If you restart your agent or fail over to a secondary agent, there is a five minute timeout before data is sent to the central MMS servers.
The MMS agent only supports MongoDB 1.6.x+
The MMS agent currently does not support Python 3.x
Important
------------
If you have thousands of databases or collections, you should disable "DB Stats" on the "Settings" page before starting your agent.
Collecting db stats on thousands of databases or collections can adversely impact performance of your system.
* https://mms.10gen.com/settings
Installation
------------
* Install Python (2.4+) and pymongo (1.9+) - http://api.mongodb.org/python/current/
* For most people (on Linux) this is as easy as running: sudo easy_install pymongo
* If you do not have easy_install, typically you can run: sudo yum install python-setuptools
* For more information, see: http://pypi.python.org/pypi/setuptools
* The hashlib package must be installed if running Python 2.4
* Try (as root): easy_install hashlib - if that does not work, use: http://pypi.python.org/pypi/hashlib/20081119
* Download and unzip and then run (requires root/sudo permission to install):
* python setup.py build
* python setup.py install
* The backported hmac package must be installed if running Python 2.4
* Do *not* use pip for installing this package. Pip is not pulling the correct files.
* Try (as root): easy_install hmac - if that does not work, use: http://pypi.python.org/pypi/hmac
* Download and unzip and then run (requires root/sudo permission to install):
* python setup.py build
* python setup.py install
* If you need to install any libraries then make sure you close your session/terminal after installing and open a new one, before starting the agent.
* The agent will securely update itself as new releases are published by 10gen. The agent directory must be writable by the user the agent is running under.
* Start the agent:
nohup python agent.py > /REPLACE_SOME_DIRECTORY/agent.log 2>&1 &
Note: If you are running Python 2.4, you should reduce the default stack size for the user account the MMS agent runs under. In Python 2.5+, the agent reduces the stack size programmatically.
Hardware Monitoring - Munin Setup
------------
MMS also supports hardware monitoring on database servers. To accomplish this, MMS collects data from the ubiquitous Munin Node daemon.
Note munin-node, and hardware monitoring is only available for MongoDB instances running on Linux hosts.
The following are a list of steps to install and configure the Munin Node daemon for MMS.
* Install the munin-node module
* On the majority of OSs, this can be accomplished by using apt-get or yum - e.g., sudo yum install munin-node)
* If you install from source you must also install the plugins (described in the links below under "Additional Documentation")
* MMS currently uses the cpu, iostat and iostat_ios plugins
* Configure munin-node.conf to allow connections from the server(s) running your MMS agent(s).
* Typically, this file is located in /etc/munin/munin-node.conf
* Modify the "allow" property - See the munin-node.conf documentation for more information: http://munin-monitoring.org/wiki/munin-node.conf
* If your disk devices are numbered (e.g., /dev/sda1) then you need to configure the munin iostat plugin to support numbered disks (disabled by default).
* For a typical installation, the configuration file is: /etc/munin/plugin-conf.d/munin-node
* If this file does not exist, create and add the following:
[iostat]
env.SHOW_NUMBERED 1
* Ensure your Munin Node process is registered to start on server boot
* E.g. sudo ln -s /etc/init.d/munin-node /etc/rc3.d/S99munin-node
* Restart your Munin Node process to update the configuration:
* sudo /etc/init.d/munin-node restart
* You can verify your munin-node setup by running the following from the agent(s) nodes:
* telnet HOSTNAME 4949 (the default and required port for munin-node)
* fetch iostat
* fetch iostat_ios
* fetch cpu
(each command should be on a separate line - i.e., hit return after fetch COMMAND - if the plugins are not installed you will see '# Unknown service')
* Additional Documentation
* http://munin-monitoring.org/wiki/munin-node
* http://munin-monitoring.org/wiki/LinuxInstallation
* http://munin-monitoring.org/wiki/SolarisInstallation
* http://munin-monitoring.org/wiki/HowToMonitorWindows
* http://munin-monitoring.org
Firewall
-------------
If your datacenter is secured by a firewall, please configure your firewall to allow outbound connections on port 443 (SSL) to mms.10gen.com
Proxy
-------------
If your datacenter requires outbound connections to route through a proxy, you can add the following environment variable:
export https_proxy='http://someProxyServer:port';
(on Windows use HTTPS_PROXY)
Note: This requires Python 2.6.1+
Data Collected
-------------
Different commands are executed based on the host type. Below is an overall list of commands/queries executed.
* Default
* serverStatus
* buildinfo
* getCmdLineOpts
* connPoolStats
* _isSelf
* getParameter
* ismaster
* getShardVersion
* netstat
* replSetGetStatus
* shards.find
* mongos.find
* config.chunks.group
* oplog.find
* collstats - oplog.rs
* sources.find (slave)
* config.settings.find
* config.collections.find
* config.databases.find
* config.lockpings.find
* dbstats
* db.locks
* Enabled By User
* profiler.find
For more information see:
* https://groups.google.com/forum/#!forum/10gen-mms
To submit a support request:
* https://jira.mongodb.org/secure/CreateIssue.jspa?pid=10582&issuetype=6

View file

@ -1,57 +0,0 @@
Contents
------------
* README.txt
* mongommsinstall.bat
* mongommstinstall.ps1
* srvany.exe
Prerequisites
------------
* Expects a MMS/PyMongo compatible python version to be installed
* Expects pymongo to be installed
* Powershell version 2.0 (for windows service installation)
* Powershell script execution to be turned on
Installation
------------
* The following instructions are to run MMS as a windows service
* More information can be found at https://mms.10gen.com/help/install.html#installing-mms-on-windows
Install Prerequisites
---------------------
* Install python 2.7.x using the Windows Installer. 64 bit installer is preferred.
e.g. http://www.python.org/ftp/python/2.7.2/python-2.7.2.amd64.msi
* Install latest version of pymongo using the Windows Installer from pypi. Ensure
you pick the installer that corresponds to your python version and the type (32 bit or 64 bit).
http://pypi.python.org/pypi/pymongo/
Install Powershell 2.0
----------------------
* If you do not have powershell 2.0 installed you would need to install it from http://support.microsoft.com/kb/968929.
Enable Powershell Script Execution
----------------------------------
* Open the Windows Powershell by right-clicking its icon in the Start bar and selecting Run as Administrator
* Type `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned` and agree when prompted about changing the policy
Specifying a Proxy Server
-------------------------
If the MMS agent needs a proxy server to connect outside, specify it in the HTTPS_PROXY environment variable
as http://proxyservername:port
Sevice Installation
-------------------
* The script reads python path from windows registry if not specified on command line
* If multiple python installations are present edit the bat file to specify the path of the python install to work
* Run mongommsinstall.bat from an administrator command window
* This will install the windows service and start it
* If you stop the windows service, the agent will stop
Uninstall
---------
- Stop the "MongoDB MMS" windows service
- Run "sc delete mongomms"
More Information
----------------
- MMS Help https://mms.10gen.com/help/

View file

@ -1,336 +0,0 @@
"""
(C) Copyright 2011, 10gen
This is a label on a mattress. Do not modify this file!
"""
# App
import settings as _settings
import logConfig
# Python
import sys, socket, time, os, hmac, urllib.request, urllib.error, urllib.parse, threading, subprocess, traceback
try:
import hashlib
except ImportError:
sys.exit( 'ERROR - you must have hashlib installed - see README for more info' )
_logger = logConfig.initLogger()
socket.setdefaulttimeout( _settings.socket_timeout )
_pymongoVersion = None
_processPid = os.getpid()
# Try and reduce the stack size.
try:
threading.stack_size( 409600 )
except:
pass
if _settings.mms_key == '@API_KEY@':
sys.exit( 'ERROR - you must set your @API_KEY@ - see https://mms.10gen.com/settings' )
if _settings.secret_key == '@SECRET_KEY@':
sys.exit( 'ERROR - you must set your @SECRET_KEY@ - see https://mms.10gen.com/settings' )
if sys.version_info < ( 2, 4 ):
sys.exit( 'ERROR - old Python - the MMS agent requires Python 2.4 or higher' )
# Make sure pymongo is installed
try:
import pymongo
import bson
except ImportError:
sys.exit( 'ERROR - pymongo not installed - see: http://api.mongodb.org/python/ - run: easy_install pymongo' )
# Check the version of pymongo.
pyv = pymongo.version
if "partition" in dir( pyv ):
pyv = pyv.partition( "+" )[0]
_pymongoVersion = pyv
if list(map( int, pyv.split('.') )) < [ 1, 9]:
sys.exit( 'ERROR - The MMS agent requires pymongo 1.9 or higher: easy_install -U pymongo' )
if _settings.useSslForAllConnections:
if list(map( int, pyv.split('.') )) < [ 2, 1, 1]:
sys.exit( 'ERROR - The MMS agent requires pymongo 2.1.1 or higher to use SSL: easy_install -U pymongo' )
_pymongoVersion = pymongo.version
class AgentProcessContainer( object ):
""" Store the handle and lock to the agent process. """
def __init__( self ):
""" Init the lock and init process to none """
self.lock = threading.Lock()
self.agent = None
def pingAgentProcess( self ):
""" Ping the agent process """
try:
self.lock.acquire()
if self.agent is None or self.agent.poll() is not None:
return
self.agent.stdin.write( 'hello\n' )
self.agent.stdin.flush()
finally:
self.lock.release()
def stopAgentProcess( self ):
""" Send the stop message to the agent process """
try:
self.lock.acquire()
if self.agent is None or self.agent.poll() is not None:
return
self.agent.stdin.write( 'seeya\n' )
self.agent.stdin.flush()
time.sleep( 1 )
self.agent = None
finally:
self.lock.release()
class AgentShutdownListenerThread( threading.Thread ):
""" Disabled by default. When enabled listens for shutdown messages. """
def __init__( self, loggerObj, settingsObj ):
""" Initialize the object """
self.logger = loggerObj
self.settings = settingsObj
threading.Thread.__init__( self )
def run( self ):
""" Listen for the shutdown messages """
try:
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
sock.bind( ( self.settings.shutdownAgentBindAddr, self.settings.shutdownAgentBindPort ) )
except Exception as e:
self.logger.error( traceback.format_exc( e ) )
self.logger.info( 'Shutdown listener bound to address %s on port %d' % ( self.settings.shutdownAgentBindAddr, self.settings.shutdownAgentBindPort ) )
while True:
try:
time.sleep( 5 )
data, addr = sock.recvfrom( 1024 )
if data != self.settings.shutdownAgentBindChallenge:
self.logger.error( 'received bad shutdown message from: %s' % addr[0] )
else:
self.logger.info( 'received valid shutdown message from: %s - exiting' % addr[0] )
os._exit( 0 )
except:
pass
class AgentProcessMonitorThread( threading.Thread ):
""" Make sure the agent process is running """
def __init__( self, logger, agentDir, processContainerObj ):
""" Initialize the object """
self.logger = logger
self.agentDir = agentDir
self.processContainer = processContainerObj
threading.Thread.__init__( self )
def _launchAgentProcess( self ):
""" Execute the agent process and keep a handle to it. """
return subprocess.Popen( [ sys.executable, os.path.join( sys.path[0], 'agentProcess.py' ), str( _processPid ) ], stdin=subprocess.PIPE, stdout=subprocess.PIPE )
def run( self ):
""" If the agent process is not alive, start the process """
while True:
try:
time.sleep( 5 )
self._monitorProcess()
except Exception as e:
self.logger.error( traceback.format_exc( e ) )
def _monitorProcess( self ):
""" Monitor the child process """
self.processContainer.lock.acquire()
try:
try:
if self.processContainer.agent is None or self.processContainer.agent.poll() is not None:
self.processContainer.agent = self._launchAgentProcess()
except Exception as e:
self.logger.error( traceback.format_exc( e ) )
finally:
self.processContainer.lock.release()
class AgentUpdateThread( threading.Thread ):
""" Check to see if updates are available - if so download and restart agent process """
def __init__( self, logger, agentDir, settingsObj, processContainerObj ):
""" Initialize the object """
self.logger = logger
self.agentDir = agentDir
self.settings = settingsObj
self.processContainer = processContainerObj
threading.Thread.__init__( self )
def run( self ):
""" Update the agent if possible """
while True:
try:
time.sleep( 300 )
self._checkForUpdate()
except Exception as e:
self.logger.error( 'Problem with upgrade check: ' + traceback.format_exc( e ) )
def _checkForUpdate( self ):
""" Update the agent if possible """
res = urllib.request.urlopen( self.settings.version_url % { 'key' : self.settings.mms_key } )
resBson = None
try:
resBson = bson.decode_all( res.read() )
finally:
if res is not None:
res.close()
res = None
if len(resBson) != 1:
return
versionResponse = resBson[0]
if 'status' not in versionResponse or versionResponse['status'] != 'ok':
return
if 'agentVersion' not in versionResponse or 'authCode' not in versionResponse:
return
remoteAgentVersion = versionResponse['agentVersion']
authCode = versionResponse['authCode']
if authCode != hmac.new( self.settings.secret_key, remoteAgentVersion, digestmod=hashlib.sha1 ).hexdigest():
self.logger.error( 'Invalid auth code - please confirm your secret key (defined on Settings page) is correct and hmac is properly installed - http://mms.10gen.com/help/' )
return
if self._shouldUpgradeAgent( self.settings.settingsAgentVersion, remoteAgentVersion ):
self._upgradeAgent( remoteAgentVersion )
def _shouldUpgradeAgent( self, localVersion, remoteVersion ):
""" Returns true if the agent should upgrade itself. """
try:
for l, r in zip( localVersion.split('.'), remoteVersion.split('.') ):
if int( l ) < int( r ):
return True
if int( l ) > int( r ):
return False
except Exception:
self.logger.error( "Upgrade problem with versions - local: '%s' - remote: '%s'" % ( localVersion, remoteVersion ) )
return False
def _upgradeAgent( self, newAgentVersion ):
""" Pull down the files, verify and then stop the current process """
res = urllib.request.urlopen( self.settings.upgrade_url % { 'key' : self.settings.mms_key } )
resBson = None
try:
resBson = bson.decode_all( res.read() )
finally:
if res is not None:
res.close()
res = None
if len(resBson) != 1:
return
upgradeResponse = resBson[0]
if 'status' not in upgradeResponse or upgradeResponse['status'] != 'ok' or 'files' not in upgradeResponse:
return
# Verify the auth codes for all files and names first.
for fileInfo in upgradeResponse['files']:
if fileInfo['fileAuthCode'] != hmac.new( self.settings.secret_key, fileInfo['file'], digestmod=hashlib.sha1 ).hexdigest():
self.logger.error( 'Invalid file auth code for upgrade - cancelling' )
return
if fileInfo['fileNameAuthCode'] != hmac.new( self.settings.secret_key, fileInfo['fileName'], digestmod=hashlib.sha1 ).hexdigest():
self.logger.error( 'Invalid file name auth code for upgrade - cancelling' )
return
# Write the files.
for fileInfo in upgradeResponse['files']:
fileContent = fileInfo['file']
fileName = fileInfo['fileName']
# If the user has a global username/password defined, make sure it is set in the new settings.py file.
if fileName == 'settings.py' and getattr( self.settings, 'globalAuthUsername', None ) is not None and getattr( self.settings, 'globalAuthPassword', None ) is not None:
fileContent = fileContent.replace( 'globalAuthPassword = None', 'globalAuthPassword=%r' % self.settings.globalAuthPassword )
fileContent = fileContent.replace( 'globalAuthUsername = None', 'globalAuthUsername=%r' % self.settings.globalAuthUsername )
fileSystemName = os.path.join( self.agentDir, fileName )
newFile = open( fileSystemName, 'w' )
try:
newFile.write( fileContent )
finally:
if newFile is not None:
newFile.close()
# Stop the current agent process
try:
self.processContainer.stopAgentProcess()
self.settings.settingsAgentVersion = newAgentVersion
self.logger.info( 'Agent upgraded to version: ' + newAgentVersion + ' - there is up to a five minute timeout before data will be sent again' )
except Exception as e:
self.logger.error( 'Problem restarting agent process: ' + traceback.format_exc( e ) )
#
# Run the process monitor and update threads.
#
if __name__ == "__main__":
try:
_logger.info( 'Starting agent parent process - version: %s' % ( _settings.settingsAgentVersion ) )
_logger.info( 'Note: If you have hundreds or thousands of databases, disable dbstats on the settings page before running the MMS agent.' )
processContainer = AgentProcessContainer()
# Star the agent monitor thread.
monitorThread = AgentProcessMonitorThread( _logger, sys.path[0], processContainer )
monitorThread.setName( 'AgentProcessMonitorThread' )
monitorThread.setDaemon( True )
monitorThread.start()
# If enabled, start the shutdown listener thread (disabled by default).
if _settings.shutdownAgentBindAddr is not None:
shutdownListenerThread = AgentShutdownListenerThread( _logger, _settings )
shutdownListenerThread.setName( 'AgentShutdownListenerThread' )
shutdownListenerThread.setDaemon( True )
shutdownListenerThread.start()
if _settings.autoUpdateEnabled:
updateThread = AgentUpdateThread( _logger, sys.path[0], _settings, processContainer )
updateThread.setName( 'AgentUpdateThread' )
updateThread.setDaemon( True )
updateThread.start()
_logger.info( 'Started agent parent process - version: %s' % ( _settings.settingsAgentVersion ) )
# The parent process will let the child process know it's alive.
while True:
try:
time.sleep( 2 )
processContainer.pingAgentProcess()
except Exception as exc:
_logger.error( traceback.format_exc( exc ) )
except KeyboardInterrupt:
processContainer.stopAgentProcess()
except Exception as ex:
_logger.error( traceback.format_exc( ex ) )

View file

@ -1,289 +0,0 @@
"""
(C) Copyright 2011, 10gen
This is a label on a mattress. Do not modify this file!
"""
# Mongo
import pymongo, bson
if '_closed' in dir( pymongo.connection ):
pymongo.connection._closed = lambda sock: False
# App
import settings as _settings
from mmsAgent import MmsAgent
from confPull import ConfPullThread
import logConfig
# Python
import os, sys, platform, time, threading, socket, traceback, random, hashlib, tempfile
socket.setdefaulttimeout( _settings.socket_timeout )
_agentVersion = "1.5.7"
_pymongoVersion = pymongo.version
_pymongoHasC = False
try:
_pymongoHasC = pymongo.has_c()
except:
pass
# Try and reduce the stack size.
try:
threading.stack_size(409600)
except:
pass
class AgentProcess( threading.Thread ):
""" The parent process - monitors agent process and checks for updates etc """
def __init__( self, loggerObj, agentDir, existingSessionKey ):
""" Construct the object """
self.logger = loggerObj
self.agentDir = agentDir
self.mmsAgent = MmsAgent( _settings, _agentVersion, platform.python_version(), _pymongoVersion, _pymongoHasC, platform.uname()[1], self.logger, existingSessionKey )
threading.Thread.__init__( self )
def stop( self ):
""" Stop the agent process """
try:
self.mmsAgent.done = True
self.mmsAgent.stopAll()
except Exception as fe:
self.logger.error( traceback.format_exc( fe ) )
def run( self ):
""" The agent process """
try:
# Start the configuration request
confThread = ConfPullThread( _settings, self.mmsAgent )
confThread.setName( 'ConfPullThread' )
confThread.start()
hostStateMonitorThread = MonitorHostState( self.logger, self.mmsAgent )
hostStateMonitorThread.setName( 'MonitorHostState' )
hostStateMonitorThread.start()
# Loop through and send data back to the MMS servers.
while not self.mmsAgent.done:
try:
try:
self.mmsAgent.sendDataToMms()
except Exception as e:
self.logger.error( traceback.format_exc( e ) )
finally:
try:
time.sleep( self.mmsAgent.collectionInterval )
except:
pass
except Exception as e:
self.logger.error( traceback.format_exc( e ) )
class ParentProcessMonitor( threading.Thread ):
""" The parent process monitor - monitors to see if the parent process is sending heartbeats """
def __init__( self, agentProcessObj ):
""" Construct the object """
self.mmsAgent = agentProcessObj.mmsAgent
self.logger = self.mmsAgent.logger
self.agentProcess = agentProcessObj
self.lock = threading.Lock()
self.lastHeartbeat = time.time()
self.running = True
threading.Thread.__init__( self )
def run( self ):
""" Verify the parent process is sending pings """
while self.running:
time.sleep( 2 )
try:
self._check()
except Exception as ex:
self.logger.error( traceback.format_exc( ex ) )
raise
def _check( self ):
""" Verify the heartbeat """
try:
self.lock.acquire()
secsSinceHeartbeat = ( time.time() - self.lastHeartbeat )
if secsSinceHeartbeat > 10:
self.agentProcess.stop()
os._exit( 0 )
finally:
self.lock.release()
def stop( self ):
""" Stop the process """
self.running = False
def heartbeat( self ):
""" Update the last time a message was sent from the parent. """
try:
self.lock.acquire()
self.lastHeartbeat = time.time()
finally:
self.lock.release()
class ParentMsgReader( threading.Thread ):
""" The parent process message reader """
def __init__( self, loggerObj, agentProcessObj, parentMonitorObj ):
""" Construct the object """
self.logger = loggerObj
self.parentMonitor = parentMonitorObj
self.agentProcess = agentProcessObj
threading.Thread.__init__( self )
def run( self ):
""" Read the data from stdin and process """
while True:
try:
time.sleep( 1 )
self._readParentMessage()
except Exception as exc:
self.logger.error( traceback.format_exc( exc ) )
def _readParentMessage( self ):
""" Read the heartbeat or stop message from the parent process """
line = sys.stdin.readline()
if not line:
return
if line == 'hello\n':
self.parentMonitor.heartbeat()
return
if line == 'seeya\n':
try:
self.agentProcess.stop()
self.parentMonitor.stop()
finally:
os._exit( 0 )
class MonitorHostState( threading.Thread ):
""" Check to see if we're not getting updates to host state - if not, flush """
def __init__( self, loggerObj, mmsAgentObj ):
""" Construct the object """
self.logger = loggerObj
self.mmsAgent = mmsAgentObj
threading.Thread.__init__( self )
def run( self ):
""" Make sure the data is current, if not remove """
while True:
try:
self.mmsAgent.cleanHostState()
except Exception as e:
self.logger.error( traceback.format_exc( e ) )
time.sleep( 10 )
def generateSessionKey( *args ):
""" Generate a session key """
t = time.time() * 1000
r = random.random()*100000000000000000
try:
a = platform.uname()[1]
except:
a = random.random()*100000000000000000
return hashlib.md5( ( '%(time)s %(random)s %(host)s %(args)s' % {'time' : t, 'random': r, 'host' : a, 'args' : str( args ) } ).encode('utf-8') ).hexdigest()
def readTmpFile( processPid ):
""" Read the temp file """
fileName = os.path.join( tempfile.gettempdir(), 'mms-' + str( processPid ) )
if not os.path.isfile( fileName ):
return None
f = open( fileName )
try:
fileContent = f.read()
# Handle the legacy json files
if fileContent.startswith( '{' ):
os.remove( fileName )
return None
resBson = bson.decode_all( fileContent )
if len(resBson) != 1:
return None
return resBson[0]
finally:
f.close()
def writeTmpFile( processPid, content ):
""" Write the temp file """
fileName = os.path.join( tempfile.gettempdir(), 'mms-' + str( processPid ) )
f = open( fileName, 'wb', 0 )
try:
f.write( bson.BSON.encode( content) )
finally:
f.close()
if __name__ == "__main__":
logger = logConfig.initLogger()
logger.info( 'Starting agent process - version %s' % ( _agentVersion ) )
sessionKey = generateSessionKey()
parentPid = None
try:
if len( sys.argv ) > 1:
parentPid = sys.argv[1]
currentState = readTmpFile( parentPid )
if currentState is not None:
if 'sessionKey' in currentState:
sessionKey = currentState['sessionKey']
else:
currentState['sessionKey'] = sessionKey
else:
currentState = { }
currentState['sessionKey'] = sessionKey
writeTmpFile( parentPid, currentState )
except Exception as ec:
logger.error( traceback.format_exc( ec ) )
try:
# Star the agent monitor thread.
agentProcess = AgentProcess( logger, sys.path[0], sessionKey )
agentProcess.setName( 'AgentProcess' )
agentProcess.start()
parentMonitor = ParentProcessMonitor( agentProcess )
parentMonitor.setName( 'ParentProcessMonitor' )
parentMonitor.start()
msgReader = ParentMsgReader( logger, agentProcess, parentMonitor)
msgReader.setName( 'ParentMsgReader' )
msgReader.start()
logger.info( 'Started agent process - parent pid: %s - version: %s' % ( str( parentPid ), _agentVersion ) )
except Exception as ec:
logger.error( traceback.format_exc( ec ) )

View file

@ -1,304 +0,0 @@
"""
(C) Copyright 2011, 10gen
This is a label on a mattress. Do not modify this file!
"""
import threading, time, datetime, pymongo, traceback, socket, warnings
warnings.simplefilter( 'ignore', DeprecationWarning )
blockingStatsAgentVersion = "1.5.7"
class BlockingMongoStatsThread( threading.Thread ):
""" Pull the blocking data from the various hosts. """
def __init__( self, hostKey, mmsAgent):
""" Initialize the object """
self.hostKey = hostKey
self.mmsAgent = mmsAgent
self.logger = mmsAgent.logger
self.slowDbStats = False
self.lastDbStatsCheck = time.time()
self.running = True
self.host = mmsAgent.extractHostname( hostKey )
self.port = mmsAgent.extractPort( hostKey )
threading.Thread.__init__( self )
def stopThread( self ):
""" Stop the thread """
self.running = False
def run( self ):
""" Pull the data from the various hosts. """
self.logger.info( 'starting blocking stats monitoring: ' + self.hostKey )
sleepTime = ( self.mmsAgent.collectionInterval / 2 ) - 1
if ( sleepTime < 1 ):
sleepTime = 1
monitorConn = None
passes = 0
while not self.mmsAgent.done and self.running:
try:
time.sleep( sleepTime )
passes = passes + 1
if passes % 60 == 0:
monitorConn = self.mmsAgent.closeDbConnection( self.hostKey, monitorConn )
if not monitorConn:
monitorConn = self.mmsAgent.getDbConnection( self.hostKey )
if not self._collectBlockingStats( passes, monitorConn ):
monitorConn = self.mmsAgent.closeDbConnection( self.hostKey, monitorConn )
except Exception as e:
monitorConn = self.mmsAgent.closeDbConnection( self.hostKey, monitorConn )
self.logger.error( 'Problem collecting blocking data from: ' + self.hostKey + " - exception: " + traceback.format_exc( e ) )
self.logger.info( 'stopping blocking stats monitoring: ' + self.hostKey )
self.mmsAgent.closeDbConnection( self.hostKey, monitorConn )
def _collectBlockingStats( self, passes, monitorConn ):
""" Collect the blocking stats from the hosts """
try:
if not self.mmsAgent.haveHostDef( self.hostKey ):
return False
# Close the connection once per hour
# Verify the connection.
if not self.mmsAgent.isValidMonitorConn( self.hostKey, monitorConn ):
return False
stats = self._collectStats( passes, monitorConn )
try:
stats['hostIpAddr'] = socket.gethostbyname(self.hostKey[0 : self.hostKey.find( ':' )])
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'hostIpAddr', e )
stats['host'] = self.host
stats['port'] = self.port
# Make sure we ended up with the same connection.
if not self.mmsAgent.isValidMonitorConn( self.hostKey, monitorConn ):
return False
self.mmsAgent.setHostState( self.hostKey, 'mongoBlocking', stats )
return True
except Exception as e:
self.logger.error( 'Problem collecting blocking data from (check if it is up and DNS): ' + self.hostKey + " - exception: " + traceback.format_exc( e ) )
return False
def _collectStats( self, passes, monitorConn ):
""" Make the call to mongo host and collect the blocking data """
root = {}
# Set the agent version and hostname.
root['agentVersion'] = self.mmsAgent.agentVersion
root['agentHostname'] = self.mmsAgent.agentHostname
isMaster = monitorConn.admin.command( 'ismaster' )
root['isMaster'] = isMaster
isMongos = ( 'msg' in isMaster and isMaster['msg'] == 'isdbgrid' )
# Check to see if this is a mongod host
try:
if isMaster['ismaster'] == True and isMongos:
# Look at the shards
root['shards'] = list( monitorConn.config.shards.find() )
# Pull from config.locks
try:
root['locks'] = list( monitorConn.config.locks.find( limit=200, sort=[ ( "$natural" , pymongo.DESCENDING ) ]) )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'config.locks.find', e )
# Pull from config.collections if enabled
try:
if self.mmsAgent.settings.configCollectionsEnabled:
root['configCollections'] = list( monitorConn.config.collections.find( limit=200, sort=[ ( "$natural" , pymongo.DESCENDING ) ] ) )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'config.collections.find', e )
# Pull from config.databases if enabled
try:
if self.mmsAgent.settings.configDatabasesEnabled:
root['configDatabases'] = list( monitorConn.config.databases.find( limit=200, sort=[ ( "$natural" , pymongo.DESCENDING ) ] ) )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'config.databases.find', e )
try:
root['configLockpings'] = list( monitorConn.config.lockpings.find( limit=200, sort=[ ( "$natural" , pymongo.DESCENDING ) ] ) )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'config.lockpings.find', e )
# Look at the mongos instances - only pull hosts that have a ping time
# updated in the last twenty minutes (and max 1k).
queryTime = datetime.datetime.utcnow() - datetime.timedelta( seconds=1200 )
root['mongoses'] = list( monitorConn.config.mongos.find( { 'ping' : { '$gte' : queryTime } } ).limit( 1000 ) )
# Get the shard chunk counts.
shardChunkCounts = []
positions = { }
counter = 0
if passes % 10 == 0:
for chunk in monitorConn.config.chunks.find():
key = chunk['ns'] + chunk['shard']
if key not in positions:
count = {}
positions[key] = counter
shardChunkCounts.append( count )
counter = counter + 1
count['count'] = 0
count['ns'] = chunk['ns']
count['shard'] = chunk['shard']
shardChunkCounts[positions[key]]['count'] = shardChunkCounts[positions[key]]['count'] + 1
root['shardChunkCounts'] = shardChunkCounts
except pymongo.errors.OperationFailure:
pass
root['serverStatus'] = monitorConn.admin.command( 'serverStatus' )
isReplSet = False
isArbiter = False
if 'repl' in root['serverStatus']:
# Check to see if this is a replica set
try:
root['replStatus'] = monitorConn.admin.command( 'replSetGetStatus' )
if root['replStatus']['myState'] == 7:
isArbiter = True
isReplSet = True
except pymongo.errors.OperationFailure:
pass
if isReplSet:
oplog = "oplog.rs"
else:
oplog = "oplog.$main"
try:
root['localSystemReplSet'] = monitorConn.local.system.replset.find_one()
except pymongo.errors.OperationFailure as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'local.system.replset.findOne', e )
localConn = monitorConn.local
oplogStats = {}
# Get oplog status
if isArbiter:
# Do nothing for the time being
pass
elif isMaster['ismaster'] == True or isReplSet:
try:
oplogStats["start"] = localConn[oplog].find( limit=1, sort=[ ( "$natural" , pymongo.ASCENDING ) ], fields={ 'ts' : 1 } )[0]["ts"]
oplogStats["end"] = localConn[oplog].find( limit=1, sort=[ ( "$natural" , pymongo.DESCENDING ) ], fields={ 'ts' : 1} )[0]["ts"]
oplogStats['rsStats'] = localConn.command( {'collstats' : 'oplog.rs' } )
except pymongo.errors.OperationFailure as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'local.' + oplog + '.find', e )
else:
# Slave
try:
oplogStats["sources"] = {}
for s in localConn.sources.find():
oplogStats["sources"][s["host"]] = s
except pymongo.errors.OperationFailure as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'local.sources.find', e )
root["oplog"] = oplogStats
# Load the config.gettings collection (balancer info etc.)
if not isArbiter:
try:
root['configSettings'] = list( monitorConn.config.settings.find() )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'config.settings.find', e )
# per db info - mongos doesn't allow calls to local
root['databases'] = { }
root['dbProfiling'] = { }
root['dbProfileData'] = { }
profilerEnabled = self.mmsAgent.hostDefValue( self.hostKey, 'profiler' )
if ( passes % 20 == 0 or profilerEnabled ) and not isArbiter and not isMongos:
count = 0
for x in monitorConn.database_names():
try:
if passes % 20 == 0:
if self.slowDbStats and ( ( time.time() - self.lastDbStatsCheck ) < 7200 ):
continue
if not self.mmsAgent.disableDbstats:
count += 1
if count > 100:
break
startTime = time.time()
temp = monitorConn[x].command( 'dbstats' )
# work around Python 2.4 and older bug
for f in temp:
# this is super hacky b/c of Python 2.4
if isinstance( temp[f] , (int, float, complex)) and str(temp[f]) == "-inf":
temp[f] = 0
root['databases'][x] = temp
if ( time.time() - startTime ) > 6:
self.slowDbStats = True
else:
self.slowDbStats = False
self.lastDbStatsCheck = time.time()
# If the profiler is enabled in MMS, collect data
if profilerEnabled and not isArbiter and not self.mmsAgent.settings.disableProfileDataCollection:
try:
# Get the most recent entries.
profileData = list( monitorConn[x].system.profile.find( spec=None, fields=None, skip=0, limit=20, sort=[ ( "$natural", pymongo.DESCENDING ) ] ) )
if len( profileData ) > 0:
root['dbProfileData'][x] = profileData
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'system.profile.find-' + x, e )
# Check to see if the profiler is enabled
try:
profiling = monitorConn[x].command( { 'profile' : -1 } )
if profiling is not None and 'ok' in profiling:
del profiling['ok']
root['dbProfiling'][x] = profiling
except Exception:
pass
except:
continue
if 'serverStatus' in root:
del root['serverStatus']
return root

View file

@ -1,109 +0,0 @@
"""
(C) Copyright 2011, 10gen
This is a label on a mattress. Do not modify this file!
"""
import threading, time, urllib.request, urllib.error, urllib.parse, traceback
import bson
confPullAgentVersion = "1.5.7"
class ConfPullThread( threading.Thread ):
""" The remote configuration pull thread object """
def __init__( self, settings, mmsAgent):
""" Initialize the object """
self.settings = settings
self.logger = mmsAgent.logger
self.mmsAgent = mmsAgent
self.confUrl = self.settings.config_url % {
'key' : self.settings.mms_key,
'hostname' : self.mmsAgent.agentHostname,
'sessionKey' : self.mmsAgent.sessionKey,
'agentVersion' : self.mmsAgent.agentVersion,
'srcVersion' : self.mmsAgent.srcVersion
}
threading.Thread.__init__( self )
def run( self ):
""" Pull the configuration from the cloud (if enabled) """
while not self.mmsAgent.done:
self._pullRemoteConf()
time.sleep( self.mmsAgent.confInterval )
def _pullRemoteConf( self ):
""" Pull the remote configuration data """
uniqueHostnames = []
res = None
try:
res = urllib.request.urlopen( self.confUrl )
resBson = None
try:
resBson = bson.decode_all( res.read() )
finally:
if res is not None:
res.close()
res = None
if len(resBson) != 1:
return
confResponse = resBson[0]
if 'hosts' not in confResponse:
self.mmsAgent.stopAll()
return
if 'disableDbstats' in confResponse:
self.mmsAgent.disableDbstats = confResponse['disableDbstats']
else:
self.mmsAgent.disableDbstats = False
hosts = confResponse['hosts']
self.mmsAgent.serverHostDefsLock.acquire()
try:
# Extract the host information
if hosts is not None:
for host in hosts:
hostDef, hostDefLast = self.mmsAgent.extractHostDef( host )
hostKey = hostDef['hostKey']
uniqueHostnames.append( hostKey )
if hostKey not in self.mmsAgent.serverHostDefs:
self.mmsAgent.startMonitoringThreads( hostDef )
else:
self.mmsAgent.checkChangedHostDef( hostDef, hostDefLast )
hostDef = None
hostDefLast = None
# Check to see if anything was removed
for hostDef in list(self.mmsAgent.serverHostDefs.values()):
if hostDef['hostKey'] not in uniqueHostnames:
self.mmsAgent.stopAndClearHost( hostDef['hostKey'] )
finally:
self.mmsAgent.serverHostDefsLock.release()
except Exception as e:
if res is not None:
try:
res.close()
res = None
except:
pass
self.logger.warning( "Problem pulling configuration data from MMS (check firewall and network): " + traceback.format_exc( e ) )

View file

@ -1,130 +0,0 @@
"""
(C) Copyright 2012, 10gen
This is a label on a mattress. Do not modify this file!
"""
import threading, time, traceback, warnings, sets
warnings.simplefilter( 'ignore', DeprecationWarning )
getLogsAgentVersion = "1.5.7"
class GetLogsThread( threading.Thread ):
""" When enabled pull log data from hosts. """
def __init__( self, hostKey, mmsAgent):
""" Initialize the object """
threading.Thread.__init__( self )
self.hostKey = hostKey
self.mmsAgent = mmsAgent
self.logger = mmsAgent.logger
self.running = True
self.lastLogEntries = sets.Set()
def stopThread( self ):
""" Stop the thread """
self.running = False
def run( self ):
""" Pull the data from the various hosts. """
self.logger.info( 'starting log data collection: ' + self.hostKey )
sleepTime = self.mmsAgent.logCollectionInterval
if ( sleepTime < 1 ):
sleepTime = 5
logConn = None
passes = 0
while not self.mmsAgent.done and self.running:
try:
enabled = self.mmsAgent.hostDefValue( self.hostKey, 'getLogs' )
if not enabled:
return
passes = passes + 1
# Close the connection every so often.
if passes % 120 == 0:
logConn = self.mmsAgent.closeDbConnection( self.hostKey, logConn )
if not logConn:
logConn = self.mmsAgent.getDbConnection( self.hostKey )
time.sleep( sleepTime )
if not self._processLogs( logConn ):
logConn = self.mmsAgent.closeDbConnection( self.hostKey, logConn )
except Exception as e:
logConn = self.mmsAgent.closeDbConnection( self.hostKey, logConn )
self.logger.error( 'Problem collecting log data from: ' + self.hostKey + " - exception: " + traceback.format_exc( e ) )
self.logger.info( 'stopping log data collection: ' + self.hostKey )
self.mmsAgent.closeDbConnection( self.hostKey, logConn )
def _processLogs( self, logConn ):
""" Process the logs """
try:
if not self.mmsAgent.haveHostDef( self.hostKey ):
return False
# Verify the connection.
if not self.mmsAgent.isValidMonitorConn( self.hostKey, logConn ):
return False
if not self.mmsAgent.hasCommand( 'getLog', self.hostKey, logConn ):
self.logger.error( 'This version of MongoDB does not support the getLog command' )
time.sleep( 60 )
return False
logs = self._collectLogs( logConn )
# Make sure we ended up with the same connection.
if not self.mmsAgent.isValidMonitorConn( self.hostKey, logConn ):
return False
self.mmsAgent.setHostState( self.hostKey, 'logs', logs )
return True
except Exception as e:
self.logger.error( 'Problem collecting log data from: ' + self.hostKey + " - exception: " + traceback.format_exc( e ) )
return False
def _collectLogs( self, logConn ):
""" Make the call to mongo host and pull the log data """
root = { }
logEntries = []
entries = logConn.admin.command( { 'getLog' : 'global' } )
if not entries or not entries.get('log'):
self.lastLogEntries.clear()
return root
for logEntry in entries['log']:
if logEntry in self.lastLogEntries:
continue
logEntries.append( logEntry )
if len ( logEntries ) == 0:
return root
self.lastLogEntries.clear()
for logEntry in entries['log']:
self.lastLogEntries.add( logEntry )
root['entries'] = logEntries
return root

View file

@ -1,125 +0,0 @@
"""
(C) Copyright 2011, 10gen
This is a label on a mattress. Do not modify this file!
"""
# App
import settings as _settings
# Mongo
import pymongo, bson
# Python
import logging, threading, time, logging.handlers, urllib.request, urllib.error, urllib.parse, platform, socket, queue
socket.setdefaulttimeout( _settings.socket_timeout )
class LogRelayThread( threading.Thread ):
""" The log relay thread - batch messages """
def __init__( self, recordQueue ):
""" Construct the object """
self.recordQueue = recordQueue
self.logUrl = _settings.logging_url % { 'key' : _settings.mms_key }
self.pythonVersion = platform.python_version()
try:
self.hostname = platform.uname()[1]
except:
self.hostname = 'UNKNOWN'
self.pymongoVersion = pymongo.version
threading.Thread.__init__( self )
def run( self ):
""" The agent process """
while True:
try:
# Let the records batch for five seconds
time.sleep( 5 )
self._processRecords()
except Exception:
pass
def _processRecords( self ):
""" Process the log records """
records = []
try:
while not self.recordQueue.empty():
record = self.recordQueue.get( True, 1 )
if record is None:
break
data = { }
data['levelname'] = record.levelname
data['msg'] = record.msg
data['filename'] = record.filename
data['threadName'] = record.threadName
# This is to deal with older versions of python.
try:
data['funcName'] = record.funcName
except Exception:
pass
data['process'] = record.process
data['lineno'] = record.lineno
data['pymongoVersion'] = self.pymongoVersion
data['pythonVersion'] = self.pythonVersion
data['hostname'] = self.hostname
records.append( data )
if len( records ) >= 10:
break
except queue.Empty:
pass
if len( records ) == 0:
return
# Send the data back to mms.
res = None
try:
res = urllib.request.urlopen( self.logUrl, bson.BSON.encode( { 'records' : records }, check_keys=False ) )
res.read()
finally:
if res is not None:
res.close()
class MmsRemoteHandler( logging.Handler ):
""" The mms remote log handler """
def __init__( self ):
""" Construct a new object """
logging.Handler.__init__( self )
self.recordQueue = queue.Queue( 250 )
self.logRelay = LogRelayThread( self.recordQueue )
self.logRelay.setName( 'LogRelay' )
self.logRelay.start()
def emit( self, record ):
""" Send the record to the remote servers """
try:
if record is not None:
self.recordQueue.put_nowait( record )
except Exception:
pass
def initLogger( ):
""" Initialize the logger """
logger = logging.getLogger('MMS')
streamHandler = logging.StreamHandler()
streamHandler.setFormatter( logging.Formatter('%(asctime)s %(levelname)s %(message)s') )
logger.addHandler( streamHandler )
logging.handlers.MmsRemoteHandler = MmsRemoteHandler
logger.addHandler( logging.handlers.MmsRemoteHandler() )
logger.setLevel( logging.INFO )
return logger

View file

@ -1 +0,0 @@
powershell .\mongommsinstall.ps1

View file

@ -1,195 +0,0 @@
$python64RegKey = "HKLM:\Software\Python\PythonCore\*"
$python32RegKey = "HKLM:\Software\Wow6432Node\Python\PythonCore\*"
$pythonExe = "python.exe"
$srvanyExe = "srvany.exe"
$scriptName = "agent.py"
$serviceName = "MongoMMS"
$serviceDisplayName = "MongoDB MMS"
$serviceDesc = "Service that runs the MongoDB Python MMS Script"
$serviceRegPath = Join-Path "HKLM:\SYSTEM\CurrentControlSet\Services\" $serviceName
$pyMongoTest = "pymongotest.py"
$pythonTest = "pythonversiontest.py"
function Test-PyMongo {
Param($pythonPath)
if ($pythonPath -eq $null) {
return -1
}
$res = (Start-Process -FilePath $pythonPath `
-ArgumentList $pyMongoTest -Wait -PassThru -NoNewWindow).ExitCode
return $res
}
function Test-Python-Version {
Param($pythonPath)
if ($pythonPath -eq $null) {
return -1
}
$res = (Start-Process -FilePath $pythonPath `
-ArgumentList $pythonTest -Wait -PassThru -NoNewWindow).ExitCode
return $res
}
function Test-ValidPython {
Param($pythonPath)
if ($pythonPath -eq $null) {
return -1
}
$res = Test-Python-Version($pythonPath)
if (!($res -eq 0)) {
return $res
}
$res = Test-PyMongo($pythonPath)
return $res
}
function Get-PythonPath {
Param($location)
if ($location -eq $null) {
return Get-PythonRegistryPath
}
else {
$pythonExePath = $null
if (Test-Path -LiteralPath $location -PathType Leaf) {
$pythonExePath = $location
}
else {
if (Test-Path -Path $location -PathType Container) {
$pythonExePath = Join-Path $location $pythonExe
if (!(Test-Path -Path $pythonExePath -PathType Leaf)) {
$pythonExePath = $null
}
}
else {
Write-Error "Error: Python installation cannot be found. Service not installed"
break
}
}
$res = Test-ValidPython($pythonExePath)
if ($res -eq 0) {
return $pythonExePath
}
}
return $null
}
function Get-PythonRegistryPath {
$pythonRegPath = Get-ActualPythonRegistryPath($python64RegKey)
if ($pythonRegPath -eq $null) {
$pythonRegPath = Get-ActualPythonRegistryPath($python32RegKey)
}
return $pythonRegPath
}
function Get-ActualPythonRegistryPath {
Param($registryBasePath)
if (Test-Path -Path $registryBasePath -PathType Container) {
$list = Get-Item $registryBasePath | select PSPath
foreach ($regPath in $list) {
$installPath = Join-Path $regPath.PSPath "InstallPath"
if (Test-Path -Path $installPath) {
$installPathValue = (Get-ItemProperty $installPath "(default)")."(default)"
$installPathValue = Join-Path $installPathValue $pythonExe
if (Test-Path -LiteralPath $installPathValue -PathType Leaf) {
$res = Test-ValidPython($installPathValue)
if ($res -eq 0) {
return $installPathValue
}
}
}
}
}
}
function Get-SrvanyPath {
$currentPath = Resolve-Path .
$exePath = Join-Path $currentPath $srvanyExe
if (Test-Path -LiteralPath $exePath -PathType Leaf) {
return $exePath
}
$progFilesPath = [Environment]::GetEnvironmentVariable("ProgramFiles(x86)")
if ($progFilesPath -eq $null) {
$progFilesPath = [Environment]::GetEnvironmentVariable("ProgramFiles")
}
$exePath = Join-Path $progFilesPath (Join-Path "\Windows Resource Kits\Tools" $srvanyExe)
if (Test-Path -LiteralPath $exePath -PathType Leaf) {
return $exePath
}
else {
Write-Error "Error: Windows Resource Toolkit srvany not found"
break
}
}
function Create-MMSService {
Param($execName)
$svcList = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($svcList -eq $null -or $svcList.Count -eq 0) {
New-Service -Name $serviceName -BinaryPathName $execName `
-Description $serviceDesc -DisplayName $serviceDisplayName `
-StartupType Automatic | Out-Null
}
else {
Write-Error "Service already exists"
break
}
}
function Get-MMSScriptPath {
$currentPath = Resolve-Path .
$scriptPath = Join-Path $currentPath $scriptName
if (Test-Path -LiteralPath $scriptPath -PathType Leaf) {
return $scriptPath
}
else {
Write-Error "Error: MMS Script not found"
break
}
}
function Modify-MMSService {
$appDir = Get-Item $mmsScriptPath | Split-Path -parent
$quotedAppDir = Quote-String($appDir)
$quotedPythonPath = Quote-String($pythonPath)
$quotedScriptPath = Quote-String($mmsScriptPath)
$application = $quotedPythonPath+" "+$quotedScriptPath
$parameterKey = Join-Path $serviceRegPath "Parameters"
New-Item -Path $parameterKey | Out-Null
New-ItemProperty -Path $parameterKey -Name "Application" -Value $application | Out-Null
New-ItemProperty -Path $parameterKey -Name "AppDir" -Value $quotedAppDir | Out-Null
}
function Start-MMSService {
Start-Service -Name $serviceName
}
function Quote-String {
Param($unquotedString)
return "`"" + $unquotedString + "`""
}
if ($args.Length -gt 0) {
$pythonPath = Get-PythonPath($args[0])
}
else {
$pythonPath = Get-PythonPath
}
if ($pythonPath -eq $null) {
Write-Error -Message "Valid python install not found. Service not installed" `
-Category NotInstalled
Exit
}
$srvAnyPath = Get-SrvanyPath
$mmsScriptPath = Get-MMSScriptPath
Create-MMSService(Quote-String($srvAnyPath))
Modify-MMSService
Write-Host "Service succesfully created"
Start-MMSService
Write-Host "Service started"

View file

@ -1,170 +0,0 @@
"""
(C) Copyright 2011, 10gen
This is a label on a mattress. Do not modify this file!
"""
# Python
import socket, threading, time
muninAgentVersion = "1.5.7"
def containsStr( val, query ):
""" Returns true if the value is contained in the string """
return val.find( query ) > -1
class MuninThread( threading.Thread ):
""" Pull them munin data from the various hosts. """
def __init__( self, hostname, mmsAgent ):
""" Initialize the object """
self.hostname = hostname
self.mmsAgent = mmsAgent
self.logger = mmsAgent.logger
self.muninNode = MuninNode( self.hostname )
self.running = True
threading.Thread.__init__( self )
def run( self ):
""" Pull the munin data from the various hosts. """
self.logger.info( 'starting munin monitoring: ' + self.hostname + ':4949' )
sleepTime = ( self.mmsAgent.collectionInterval / 2 ) - 1
if ( sleepTime < 1 ):
sleepTime = 1
while not self.mmsAgent.done and self.mmsAgent.hasUniqueServer( self.hostname ) and self.running:
try:
time.sleep( sleepTime )
self._collectAndSetState()
except:
pass
self.logger.info( 'stopping munin monitoring: ' + self.hostname + ':4949' )
def stopThread( self ):
""" Stop the thread. This sets a running flag to false """
self.running = False
def _collectAndSetState( self ):
""" Collect the data and set the state """
muninStats = self._collectStats()
if muninStats is None:
return
muninStats['host'] = self.hostname
self.mmsAgent.setMuninHostState( self.hostname, muninStats )
def _collectStats( self ):
""" Collect the data from the munin host """
try:
return self.muninNode.fetchAndConfigMany( [ "cpu" , "iostat" , "iostat_ios" ] )
except:
return None
class MuninNode( object ):
""" The Munin node collection object """
def __init__( self, host='127.0.0.1', port=4949 ):
""" Constructor """
self.host = host
self.port = port
def _send( self, cmd, sock ):
""" Send a command to Munin """
sock.send( cmd + "\r\n" )
def _readline( self, f ):
""" Read data from vendor.munin """
return f.readline().split("\n")[0]
def list( self, sock, f ):
""" Run a list operation """
self._send( 'list', sock )
s = self._readline( f )
return s.split( ' ' )
def config( self, cmd, sock, f ):
""" Run a config operation """
return self._data( 'config', cmd, sock, f )
def fetch( self, cmd, sock, f ):
""" Run a fetch operation """
return self._data( 'fetch', cmd, sock, f )
def _data( self, cmdType, cmd, sock, f ):
""" Collect data """
self._send( cmdType + ' ' + cmd, sock )
data = []
while True:
s = self._readline( f )
if s == ".":
break
if cmdType == 'config':
if containsStr( s, '.label' ) == False:
continue
data.append( s )
return data
def connect( self ):
""" Connect to the Munin node """
sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock.connect( ( self.host, self.port ) )
f = sock.makefile()
if not f:
try:
sock.close()
except:
pass
raise Exception( 'Error reading data from socket' )
banner = f.readline() # banner
if len( banner ) == 0:
raise Exception( 'Unable to connect to Munin' )
return ( sock, f )
def disconnect( self, sock, f ):
""" Disconnect from vendor.munin """
try:
try:
self._send( 'quit', sock )
finally:
sock.close()
finally:
if f is not None:
f.close()
def fetchAndConfigMany( self, cmdTypes ):
""" The fetch and config many cmds - opens and closes the connection """
sock = None
f = None
try:
sock, f = self.connect()
fetch = {}
config = {}
for t in cmdTypes:
fetch[t] = self.fetch( t, sock, f )
if ( t == 'cpu' ):
config[t] = { }
else:
config[t] = self.config( t, sock, f )
return { 'fetch' : fetch, 'config' : config }
finally:
try:
self.disconnect( sock, f )
except:
pass

View file

@ -1,184 +0,0 @@
"""
(C) Copyright 2011, 10gen
This is a label on a mattress. Do not modify this file!
"""
import threading, time, pymongo, traceback, warnings, datetime
warnings.simplefilter( 'ignore', DeprecationWarning )
nonBlockingStatsAgentVersion = "1.5.7"
class NonBlockingMongoStatsThread( threading.Thread ):
""" Pull the non-blocking data from the various hosts. """
def __init__( self, hostKey, mmsAgent ):
""" Initialize the object """
self.hostKey = hostKey
self.mmsAgent = mmsAgent
self.logger = mmsAgent.logger
self.running = True
self.host = mmsAgent.extractHostname( hostKey )
self.port = mmsAgent.extractPort( hostKey )
threading.Thread.__init__( self )
def stopThread( self ):
""" Stop the thread """
self.running = False
def run( self ):
""" The thread to collect stats """
self.logger.info( 'starting non-blocking stats monitoring: ' + self.hostKey )
sleepTime = ( self.mmsAgent.collectionInterval / 2 ) - 1
if ( sleepTime < 1 ):
sleepTime = 1
monitorConn = None
passes = 0
while not self.mmsAgent.done and self.running:
try:
time.sleep( sleepTime )
passes = passes + 1
# Close the connection periodically
if passes % 60 == 0:
monitorConn = self.mmsAgent.closeDbConnection( self.hostKey, monitorConn )
if not monitorConn:
monitorConn = self.mmsAgent.getDbConnection( self.hostKey )
if not self._collectNonBlockingStats( monitorConn ):
monitorConn = self.mmsAgent.closeDbConnection( self.hostKey, monitorConn )
except Exception as e:
monitorConn = self.mmsAgent.closeDbConnection( self.hostKey, monitorConn )
self.logger.error( 'Problem collecting non-blocking data from: ' + self.hostKey + " - exception: " + traceback.format_exc( e ) )
self.logger.info( 'stopping non-blocking stats monitoring: ' + self.hostKey )
self.mmsAgent.closeDbConnection( self.hostKey, monitorConn )
def _collectNonBlockingStats( self, monitorConn ):
""" Collect the non-blocking stats """
try:
if not self.mmsAgent.haveHostDef( self.hostKey ):
return False
# Verify the connection.
if not self.mmsAgent.isValidMonitorConn( self.hostKey, monitorConn ):
return False
stats = self._collectStats( monitorConn )
stats['host'] = self.host
stats['port'] = self.port
# Make sure we ended up with the same connection.
if not self.mmsAgent.isValidMonitorConn( self.hostKey, monitorConn ):
return False
self.mmsAgent.setHostState( self.hostKey, 'mongoNonBlocking', stats )
return True
except Exception as e:
self.logger.warning( 'Problem collecting non-blocking data from (check if it is up and DNS): ' + self.hostKey + ' - ' + traceback.format_exc( e ) )
return False
def _collectStats( self, monitorConn ):
""" Make the call to mongo host and collect the data """
root = {}
# Set the agent version and hostname.
root['agentVersion'] = self.mmsAgent.agentVersion
root['agentHostname'] = self.mmsAgent.agentHostname
root['agentSessionKey'] = self.mmsAgent.sessionKey
cmdStartTime = datetime.datetime.now()
root['serverStatus'] = monitorConn.admin.command( 'serverStatus' )
cmdExecTime = datetime.datetime.now() - cmdStartTime
root['serverStatusExecTimeMs'] = ( cmdExecTime.days * 24 * 60 * 60 + cmdExecTime.seconds ) * 1000 + cmdExecTime.microseconds / 1000.0
# The server build info
root['buildInfo'] = monitorConn.admin.command( 'buildinfo' )
# Try and get the command line operations
try:
root['cmdLineOpts'] = monitorConn.admin.command( 'getCmdLineOpts' )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'getCmdLineOpts', e )
# Get the connection pool stats.
try:
root['connPoolStats'] = monitorConn.admin.command( 'connPoolStats' )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'connPoolStats', e )
# Look for any startup warnings if this is a valid version of mongo.
if self.mmsAgent.hasCommand( 'getLog', self.hostKey, monitorConn ):
try:
root['startupWarnings'] = monitorConn.admin.command( { 'getLog' : 'startupWarnings' } )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'getLog.startupWarnings', e )
# See if we can get hostInfo.
if self.mmsAgent.hasCommand( 'hostInfo', self.hostKey, monitorConn ):
try:
root['hostInfo'] = monitorConn.admin.command( { 'hostInfo' : 1 } )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'hostInfo', e )
# Try and get the isSelf data
try:
root['isSelf'] = monitorConn.admin.command( '_isSelf' )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, '_isSelf', e )
# Get the params.
try:
root['getParameterAll'] = monitorConn.admin.command( { 'getParameter' : '*' } )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'getParameter.*', e )
# Check occasionally to see if we can discover nodes
isMaster = monitorConn.admin.command( 'ismaster' )
root['isMaster'] = isMaster
# Try and get the shard version
if isMaster['ismaster'] and 'msg' in isMaster:
if isMaster['msg'] != 'isdbgrid':
try:
root['shardVersion'] = monitorConn.admin.command( { 'getShardVersion' : 'mdbfoo.foo' } )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'getShardVersion.mdbfoo.foo', e )
elif isMaster['ismaster']:
try:
root['shardVersion'] = monitorConn.admin.command( { 'getShardVersion' : 'mdbfoo.foo' } )
except Exception as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'getShardVersion.mdbfoo.foo', e )
# Check to see if this is a mongod host
try:
if isMaster['ismaster'] and isMaster.get('msg', '') == 'isdbgrid':
root['netstat'] = monitorConn.admin.command( 'netstat' )
except pymongo.errors.OperationFailure as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'netstat', e )
if 'repl' in root['serverStatus']:
try:
root['replStatus'] = monitorConn.admin.command( 'replSetGetStatus' )
except pymongo.errors.OperationFailure as e:
self.mmsAgent.handleOperationFailure( self.hostKey, 'replSetGetStatus', e )
return root

View file

@ -1,7 +0,0 @@
import sys
try:
import pymongo
sys.exit(0)
except Exception as exc:
sys.exit(-1)

View file

@ -1,6 +0,0 @@
import sys
major_version=sys.version_info[0]
if major_version == 2:
sys.exit(0)
else:
sys.exit(-1)

Binary file not shown.