diff --git a/.gitignore b/.gitignore index eb7f35561..bfdf4faab 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ lib/* include/* local/* src/* +build/* diff --git a/main.py b/main.py new file mode 100644 index 000000000..791919e43 --- /dev/null +++ b/main.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +""" +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. +""" + +import sys + +from twisted.internet import reactor +from twisted.python import log + +from teeth_agent.agent import TeethAgent + +log.startLogging(sys.stdout) +agent = TeethAgent() +agent.start('localhost', 8081) +reactor.run() diff --git a/setup.py b/setup.py index fe911f4c2..a8178e7c8 100644 --- a/setup.py +++ b/setup.py @@ -18,8 +18,10 @@ limitations under the License. from setuptools import setup, find_packages +from teeth_agent import agent + setup( name='teeth-agent', - version='0.1-dev', + version=agent.AGENT_VERSION, packages=find_packages(), ) diff --git a/teeth_agent/agent.py b/teeth_agent/agent.py new file mode 100644 index 000000000..ef6c38abf --- /dev/null +++ b/teeth_agent/agent.py @@ -0,0 +1,64 @@ +""" +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. +""" + +import uuid + +import pkg_resources +import simplejson as json +from twisted.internet.protocol import ReconnectingClientFactory +from twisted.internet import reactor +from twisted.python import log + +from teeth_agent.protocol import TeethAgentProtocol + +AGENT_VERSION = '0.1-dev' + + +class AgentClientHandler(TeethAgentProtocol): + def __init__(self): + TeethAgentProtocol.__init__(self, json.JSONEncoder()) + + def connectionMade(self): + def _response(result): + log.msg('Handshake successful', connection_id=result['id']) + + self.send_command('handshake', 'a:b:c:d', AGENT_VERSION).addCallback(_response) + + +class AgentClientFactory(ReconnectingClientFactory): + protocol = AgentClientHandler + initialDelay = 1.0 + maxDelay = 120 + + + def buildProtocol(self, addr): + self.resetDelay() + return self.protocol() + + def clientConnectionFailed(self, connector, reason): + log.err('Failed to connect, re-trying', delay=self.delay) + ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) + + def clientConnectionLost(self, connector, reason): + log.err('Lost connection, re-connecting', delay=self.delay) + ReconnectingClientFactory.clientConnectionLost(self, connector, reason) + + +class TeethAgent(object): + client_factory = AgentClientFactory() + + def start(self, host, port): + reactor.connectTCP(host, port, self.client_factory) diff --git a/teeth_agent/protocol.py b/teeth_agent/protocol.py index 89a1ee899..41f3a76ec 100644 --- a/teeth_agent/protocol.py +++ b/teeth_agent/protocol.py @@ -42,16 +42,16 @@ class TeethAgentProtocol(LineReceiver): elif 'result' in message: self.handle_response(message) - def send_command(self, command): + def send_command(self, method, *args, **kwargs): message_id = str(uuid.uuid4()) d = defer.Deferred() self.pending_command_deferreds[message_id] = d self.sendLine(self.encoder.encode({ 'id': message_id, 'version': DEFAULT_PROTOCOL_VERSION, - 'method': command['method'], - 'args': command.get('args', []), - 'kwargs': command.get('kwargs', {}), + 'method': method, + 'args': args, + 'kwargs': kwargs, })) return d