Use twisted application framework

This commit is contained in:
Paul Querna 2013-09-23 23:29:55 -07:00
parent 21e7a794bd
commit 28d5eebe7e
7 changed files with 76 additions and 31 deletions

2
.gitignore vendored
View File

@ -9,3 +9,5 @@ build/*
_trial_temp/
subunit-output.txt
test-report.xml
twisted/plugins/dropin.cache
twistd.log

View File

@ -26,5 +26,5 @@ clean:
find . -name '.coverage' -delete
find . -name '_trial_coverage' -print0 | xargs --null rm -rf
find . -name '_trial_temp' -print0 | xargs --null rm -rf
rm -rf dist build *.egg-info
rm -rf dist build *.egg-info twisted/plugins/dropin.cache

View File

@ -16,11 +16,15 @@ limitations under the License.
import time
import simplejson as json
from teeth_agent.protocol import TeethAgentProtocol
from twisted.application.service import MultiService
from twisted.application.internet import TCPClient
from twisted.internet.protocol import ReconnectingClientFactory
from twisted.python.failure import Failure
from twisted.internet import reactor
from twisted.internet.defer import maybeDeferred
from twisted.internet.defer import DeferredList
from twisted.python.failure import Failure
from teeth_agent.protocol import TeethAgentProtocol
from teeth_agent.logging import get_logger
log = get_logger()
@ -59,7 +63,7 @@ class TeethClientFactory(ReconnectingClientFactory, object):
super(TeethClientFactory, self).clientConnectionLost(connector, reason)
class TeethClient(object):
class TeethClient(MultiService, object):
"""
High level Teeth Client.
"""
@ -68,18 +72,35 @@ class TeethClient(object):
def __init__(self, addrs):
super(TeethClient, self).__init__()
self.setName('teeth-agent')
self._client_encoder = self.client_encoder_cls()
self._client_factory = self.client_factory_cls(self._client_encoder, self)
self._start_time = time.time()
self._clients = []
self._outmsg = []
self._connectaddrs = addrs
self._running = False
self._handlers = {
'v1': {
'status': self._handle_status,
}
}
def startService(self):
"""Start the Service."""
super(TeethClient, self).startService()
self._running = True
self.start()
def stopService(self):
"""Stop the Service."""
super(TeethClient, self).stopService()
self._running = False
dl = []
for client in self._clients:
dl.append(client.loseConnectionSoon(timeout=0.05))
return DeferredList(dl)
def remove_endpoint(self, host, port):
"""Remove an Agent Endpoint from the active list."""
@ -101,9 +122,15 @@ class TeethClient(object):
self._clients.append(client)
def start(self):
"""Start the agent."""
"""Start the agent, if running."""
if not self._running:
return
for host, port in self._connectaddrs:
reactor.connectTCP(host, port, self._client_factory)
service = TCPClient(host, port, self._client_factory)
service.setName("teeth-agent[%s:%d]".format(host, port))
self.addService(service)
self._connectaddrs = []
def _on_command(self, topic, message):

View File

@ -14,9 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
import sys
import structlog
import twisted
CONFIGURED_LOGGING = False
@ -32,7 +30,6 @@ def configure():
CONFIGURED_LOGGING = True
twisted.python.log.startLogging(sys.stderr)
structlog.configure(
context_class=dict,
cache_logger_on_first_use=True)

View File

@ -18,6 +18,7 @@ import simplejson as json
import uuid
from twisted.internet import defer
from twisted.internet import task
from twisted.internet import reactor
from twisted.protocols.basic import LineReceiver
from twisted.python.failure import Failure
@ -100,7 +101,7 @@ class RPCProtocol(LineReceiver, EventEmitter):
"""Attempt to disconnect from the transport as 'nicely' as possible. """
self._log.info('Trying to disconnect.')
self.transport.loseConnection()
reactor.callLater(timeout, self.transport.abortConnection)
return task.deferLater(reactor, timeout, self.transport.abortConnection)
def connectionMade(self):
"""TCP hard. We made it. Maybe."""

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python
"""
Copyright 2013 Rackspace, Inc.
@ -17,17 +16,15 @@ limitations under the License.
import os
import sys
from os.path import dirname
sys.path.append(dirname(dirname(dirname(os.path.realpath(__file__)))))
from twisted.python import usage
from twisted.internet import reactor
from twisted.application.service import MultiService
from teeth_agent.logging import configure as configureLogging
from teeth_agent.agent import StandbyAgent
class Options(usage.Options):
"""Additional options for the Teeth Agent"""
synopsis = """%s [options]
""" % (
os.path.basename(sys.argv[0]),)
@ -35,24 +32,16 @@ class Options(usage.Options):
optParameters = [["mode", "m", "standbye", "Mode to run Agent in, standbye or decom."]]
def run():
if len(sys.argv) == 1:
sys.argv.append("--help")
config = Options()
try:
config.parseOptions()
except usage.error, ue:
raise SystemExit("%s: %s" % (sys.argv[0], ue))
def makeService(config):
"""Create an instance of the Teeth-Agent service."""
configureLogging()
s = MultiService()
if config['mode'] == "standbye":
agent = StandbyAgent([['localhost', 8081]])
agent.start()
agent.setServiceParent(s)
else:
raise SystemExit("Invalid mode")
reactor.run()
if __name__ == "__main__":
run()
return s

View File

@ -0,0 +1,29 @@
"""
Copyright 2013 Rackspace, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
"""
Teeth Agent Twisted Application Plugin.
"""
from twisted.application.service import ServiceMaker
TeethAgent = ServiceMaker(
"Teeth Agent Client Application",
"teeth_agent.service",
"Teeth Agent for decomissioning and standbye",
"teeth-agent"
)