manhole can now be opend/closed TTW
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1102 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
9f0cfba50d
commit
af872764f5
5 changed files with 137 additions and 58 deletions
|
@ -2,46 +2,3 @@
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from twisted.internet import reactor, protocol
|
|
||||||
from twisted.protocols import basic
|
|
||||||
from twisted.cred import portal, checkers
|
|
||||||
from twisted.conch import manhole, manhole_ssh
|
|
||||||
try:
|
|
||||||
from zope.app.publication.zopepublication import ZopePublication
|
|
||||||
from zope.app.component.hooks import setSite
|
|
||||||
hasZope = True
|
|
||||||
except:
|
|
||||||
hasZope = False
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
from cStringIO import StringIO
|
|
||||||
|
|
||||||
def getManholeFactory(namespace, **passwords):
|
|
||||||
realm = manhole_ssh.TerminalRealm()
|
|
||||||
def getManhole(_):
|
|
||||||
return manhole.Manhole(namespace)
|
|
||||||
realm.chainedProtocolFactory.protocolFactory = getManhole
|
|
||||||
p = portal.Portal(realm)
|
|
||||||
p.registerChecker(
|
|
||||||
checkers.InMemoryUsernamePasswordDatabaseDontUse(**passwords))
|
|
||||||
return manhole_ssh.ConchFactory(p)
|
|
||||||
|
|
||||||
def printTime():
|
|
||||||
print 'twisted.manhole running:', time.strftime('%H:%M:%S')
|
|
||||||
reactor.callLater(60, printTime)
|
|
||||||
|
|
||||||
#reactor.callLater(10, stopReactor)
|
|
||||||
#reactor.listenTCP(5222, EchoServerFactory())
|
|
||||||
|
|
||||||
def startup(event=None):
|
|
||||||
printTime()
|
|
||||||
d = globals()
|
|
||||||
#d['event'] = event
|
|
||||||
if hasZope and event is not None:
|
|
||||||
conn =event.database.open()
|
|
||||||
root = conn.root()[ZopePublication.root_name]
|
|
||||||
d.update(locals())
|
|
||||||
reactor.listenTCP(5001, getManholeFactory(d, admin='aaa'))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
startup()
|
|
|
@ -2,10 +2,17 @@
|
||||||
|
|
||||||
<configure
|
<configure
|
||||||
xmlns="http://namespaces.zope.org/zope"
|
xmlns="http://namespaces.zope.org/zope"
|
||||||
|
xmlns:browser="http://namespaces.zope.org/browser"
|
||||||
i18n_domain="zope"
|
i18n_domain="zope"
|
||||||
>
|
>
|
||||||
|
|
||||||
<subscriber handler="cybertools.twisted.manhole.startup"
|
<browser:page
|
||||||
for="zope.app.appsetup.interfaces.IDatabaseOpenedEvent" />
|
for="zope.app.applicationcontrol.interfaces.IApplicationControl"
|
||||||
|
name="manhole_control.html"
|
||||||
|
template="manhole_control.pt"
|
||||||
|
class=".manhole_control.ManholeControlView"
|
||||||
|
permission="zope.ManageApplication"
|
||||||
|
menu="zmi_views" title="Manhole Control"
|
||||||
|
/>
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
|
|
@ -15,7 +15,10 @@ running the manhole script.
|
||||||
|
|
||||||
In order to use it with Zope copy the cybertools.twisted-configure.zcml
|
In order to use it with Zope copy the cybertools.twisted-configure.zcml
|
||||||
to the etc/package-includes directory of your Zope instance and restart
|
to the etc/package-includes directory of your Zope instance and restart
|
||||||
Zope. You can then log in with ssh like shown above, using the username
|
Zope. Open the manhole via the "Manhole Control" Tab of the "Manage process"
|
||||||
|
menu.
|
||||||
|
|
||||||
|
You can then log in with ssh like shown above, using the username
|
||||||
and password of the zope.manager principal defined in your principals.zcml.
|
and password of the zope.manager principal defined in your principals.zcml.
|
||||||
|
|
||||||
After logging in use the `help` command to get more information.
|
After logging in use the `help` command to get more information.
|
||||||
|
@ -26,12 +29,15 @@ $Id$
|
||||||
from twisted.internet import reactor, protocol, defer
|
from twisted.internet import reactor, protocol, defer
|
||||||
from twisted.protocols import basic
|
from twisted.protocols import basic
|
||||||
from twisted.cred import portal, checkers, credentials, error as credError
|
from twisted.cred import portal, checkers, credentials, error as credError
|
||||||
from twisted.conch import manhole, manhole_ssh
|
from twisted.conch import manhole as manhole, manhole_ssh
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
try:
|
try:
|
||||||
from zope.app.publication.zopepublication import ZopePublication
|
from zope.app.publication.zopepublication import ZopePublication
|
||||||
from zope.app.component.hooks import setSite
|
from zope.app.component.hooks import setSite
|
||||||
from zope.app.security.principalregistry import principalRegistry
|
from zope.app.security.principalregistry import principalRegistry
|
||||||
|
from zope.app.security import settings
|
||||||
|
from zope.app.security.interfaces import IAuthentication
|
||||||
|
from zope.app.securitypolicy.principalrole import principalRoleManager
|
||||||
from zope.app import zapi
|
from zope.app import zapi
|
||||||
import transaction
|
import transaction
|
||||||
hasZope = True
|
hasZope = True
|
||||||
|
@ -41,10 +47,16 @@ import time
|
||||||
import sys
|
import sys
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
|
listener = None
|
||||||
|
factory = None
|
||||||
|
printLog = None
|
||||||
|
port = 5001
|
||||||
|
|
||||||
|
|
||||||
def getManholeFactory(namespace, **passwords):
|
def getManholeFactory(namespace, **passwords):
|
||||||
realm = manhole_ssh.TerminalRealm()
|
realm = manhole_ssh.TerminalRealm()
|
||||||
def getManhole(_):
|
def getManhole(_):
|
||||||
|
#return manhole.ColoredManhole(namespace)
|
||||||
return manhole.Manhole(namespace)
|
return manhole.Manhole(namespace)
|
||||||
realm.chainedProtocolFactory.protocolFactory = getManhole
|
realm.chainedProtocolFactory.protocolFactory = getManhole
|
||||||
p = portal.Portal(realm)
|
p = portal.Portal(realm)
|
||||||
|
@ -60,18 +72,26 @@ class ZopeManagerChecker(object):
|
||||||
credentialInterfaces = (credentials.IUsernamePassword,)
|
credentialInterfaces = (credentials.IUsernamePassword,)
|
||||||
|
|
||||||
def requestAvatarId(self, credentials):
|
def requestAvatarId(self, credentials):
|
||||||
manager = principalRegistry.getPrincipal('zope.manager')
|
|
||||||
login = credentials.username
|
login = credentials.username
|
||||||
password = credentials.password
|
password = credentials.password
|
||||||
if login == manager.getLogin() and manager.validate(password):
|
# TODO: This should be based on the official Zope API stuff, e.g. via:
|
||||||
return defer.succeed(login)
|
#principalRegistry = zapi.getUtility(IAuthentication)
|
||||||
|
principal = principalRegistry.getPrincipalByLogin(login)
|
||||||
|
if principal.validate(password):
|
||||||
|
roles = principalRoleManager.getRolesForPrincipal(principal.id)
|
||||||
|
for role, setting in roles:
|
||||||
|
if role == 'zope.Manager' and setting == settings.Allow:
|
||||||
|
return defer.succeed(login)
|
||||||
|
return defer.fail(credError.UnauthorizedLogin(
|
||||||
|
'Insufficient permissions'))
|
||||||
return defer.fail(credError.UnauthorizedLogin(
|
return defer.fail(credError.UnauthorizedLogin(
|
||||||
'User/password not correct'))
|
'User/password not correct'))
|
||||||
|
|
||||||
|
|
||||||
def printTime():
|
def printTime():
|
||||||
print 'twisted.manhole running:', time.strftime('%H:%M:%S')
|
global printLog
|
||||||
reactor.callLater(600, printTime)
|
print '***', time.strftime('%H:%M:%S'), '- twisted.manhole open ***'
|
||||||
|
printLog = reactor.callLater(600, printTime)
|
||||||
|
|
||||||
|
|
||||||
class Help(object):
|
class Help(object):
|
||||||
|
@ -101,23 +121,32 @@ class Help(object):
|
||||||
help = Help()
|
help = Help()
|
||||||
|
|
||||||
|
|
||||||
def startup(event=None, port=5001):
|
def open(port=5001, request=None):
|
||||||
global hasZope
|
global hasZope, factory, listener
|
||||||
printTime()
|
printTime()
|
||||||
d = globals()
|
d = globals()
|
||||||
if hasZope and event is not None:
|
if hasZope and request is not None:
|
||||||
connection = event.database.open()
|
database = request.publication.db
|
||||||
|
connection = database.open()
|
||||||
root = connection.root()[ZopePublication.root_name]
|
root = connection.root()[ZopePublication.root_name]
|
||||||
else:
|
else:
|
||||||
hasZope = False
|
hasZope = False
|
||||||
d.update(locals())
|
d.update(locals())
|
||||||
namespace = {}
|
namespace = {}
|
||||||
for key in ('__builtins__', 'connection', 'event', 'setSite', 'hasZope',
|
for key in ('__builtins__', 'connection', 'event', 'setSite', 'hasZope',
|
||||||
'zapi', 'transaction', 'root', '__doc__', 'help'):
|
'zapi', 'transaction', 'root', '__doc__', 'help',
|
||||||
|
'manholeFactory', 'context'):
|
||||||
if key in d:
|
if key in d:
|
||||||
namespace[key] = d[key]
|
namespace[key] = d[key]
|
||||||
# TODO: get admin password from somewhere else or use a real checker.
|
# TODO: get admin password from somewhere else or use a real checker.
|
||||||
reactor.listenTCP(port, getManholeFactory(namespace, admin='aaa'))
|
factory = getManholeFactory(namespace, admin='aaa')
|
||||||
|
listener = reactor.listenTCP(port, factory)
|
||||||
|
|
||||||
|
def close():
|
||||||
|
global listener
|
||||||
|
listener.stopListening()
|
||||||
|
listener = None
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
port = 5001
|
port = 5001
|
||||||
|
|
43
twisted/manhole_control.pt
Normal file
43
twisted/manhole_control.pt
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<html metal:use-macro="context/@@standard_macros/view"
|
||||||
|
i18n:domain="zope">
|
||||||
|
<head>
|
||||||
|
<title i18n:translate="">ZODB Controller</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div metal:fill-slot="body">
|
||||||
|
|
||||||
|
<tal:update condition="view/update" />
|
||||||
|
|
||||||
|
<div class="row" tal:condition="view/isOpen">
|
||||||
|
<div class="field" i18n:translate="">Manhole is open.</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" tal:condition="not:view/isOpen">
|
||||||
|
<div class="field" i18n:translate="">Manhole is closed.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="." method="post" tal:attributes="action request/URL">
|
||||||
|
<input type="hidden" name="form_submitted" value="true" />
|
||||||
|
<div class="row">
|
||||||
|
<span class="label"
|
||||||
|
i18n:translate="">Port</span>:
|
||||||
|
<input type="text" size="5" name="manhole.port"
|
||||||
|
tal:attributes="value view/port" />
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<input type="checkbox" size="5" name="manhole.setting" value="true" />
|
||||||
|
<span class="label" i18n:translate=""
|
||||||
|
tal:condition="not:view/isOpen">Open manhole</span>
|
||||||
|
<span class="label" i18n:translate=""
|
||||||
|
tal:condition="view/isOpen">Close manhole</span>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="controls">
|
||||||
|
<input type="submit" name="APPLY" value="Apply"
|
||||||
|
i18n:attributes="value apply-button"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
43
twisted/manhole_control.py
Normal file
43
twisted/manhole_control.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# This software is subject to the provisions of the Zope Public License,
|
||||||
|
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||||
|
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||||
|
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
""" Manhole Control View
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
__docformat__ = 'restructuredtext'
|
||||||
|
|
||||||
|
from cybertools.twisted import manhole
|
||||||
|
|
||||||
|
class ManholeControlView(object):
|
||||||
|
|
||||||
|
def isOpen(self):
|
||||||
|
return manhole.listener is not None
|
||||||
|
|
||||||
|
def toggleState(self):
|
||||||
|
if self.isOpen():
|
||||||
|
manhole.close()
|
||||||
|
else:
|
||||||
|
manhole.open(self.port(), self.request)
|
||||||
|
|
||||||
|
def port(self):
|
||||||
|
return manhole.port
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if not self.request.get('form_submitted'):
|
||||||
|
return
|
||||||
|
port = self.request.get('manhole.port')
|
||||||
|
if port:
|
||||||
|
manhole.port = int(port)
|
||||||
|
if self.request.get('manhole.setting', False):
|
||||||
|
self.toggleState()
|
Loading…
Add table
Reference in a new issue