From 2f5dcb896b2e3a7f3670409660c4305577edeae5 Mon Sep 17 00:00:00 2001 From: Russell Haering <russell.haering@rackspace.com> Date: Wed, 18 Dec 2013 15:47:48 -0800 Subject: [PATCH] begin on command execution --- teeth_agent/agent.py | 22 +++++++++++++-------- teeth_agent/api.py | 47 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/teeth_agent/agent.py b/teeth_agent/agent.py index 4211b5001..3cc24dc64 100644 --- a/teeth_agent/agent.py +++ b/teeth_agent/agent.py @@ -17,11 +17,11 @@ limitations under the License. from collections import OrderedDict import time -from pkg_resources import get_distribution -from teeth_rest.encoding import Serializable -from werkzeug.serving import run_simple +import pkg_resources +from teeth_rest import encoding +from werkzeug import serving -from teeth_agent.api import TeethAgentAPIServer +from teeth_agent import api class TeethAgentOperationModes(object): @@ -34,7 +34,7 @@ class TeethAgentOperationModes(object): raise RuntimeError('Invalid mode: {}'.format(mode)) -class TeethAgentStatus(Serializable): +class TeethAgentStatus(encoding.Serializable): def __init__(self, mode, started_at, version): self.mode = mode self.started_at = started_at @@ -58,7 +58,7 @@ class TeethAgent(object): self.listen_port = listen_port self.started_at = None self.mode = mode - self.api = TeethAgentAPIServer(self) + self.api = api.TeethAgentAPIServer(self) def get_status(self): """ @@ -67,9 +67,15 @@ class TeethAgent(object): return TeethAgentStatus( mode=self.mode, started_at=self.started_at, - version=get_distribution('teeth-agent').version + version=pkg_resources.get_distribution('teeth-agent').version ) + def execute_command(self, command): + """ + Execute an agent command. + """ + pass + def run(self): """ Run the Teeth Agent. @@ -78,4 +84,4 @@ class TeethAgent(object): raise RuntimeError('Agent was already started') self.started_at = time.time() - run_simple(self.listen_host, self.listen_port, self.api) + serving.run_simple(self.listen_host, self.listen_port, self.api) diff --git a/teeth_agent/api.py b/teeth_agent/api.py index 740ad58b3..29b58b197 100644 --- a/teeth_agent/api.py +++ b/teeth_agent/api.py @@ -14,13 +14,36 @@ See the License for the specific language governing permissions and limitations under the License. """ -from teeth_rest.component import APIComponent, APIServer -from teeth_rest.responses import ( - ItemResponse -) +from collections import OrderedDict + +from teeth_rest import component, encoding, errors, responses -class TeethAgentAPI(APIComponent): +class AgentCommand(encoding.Serializable): + def __init__(self, name, params): + self.name = name + self.params = params + + @classmethod + def deserialize(cls, obj): + if 'name' not in obj: + raise errors.InvalidContentError('Missing command \'name\' field.') + if 'params' not in obj: + raise errors.InvalidContentError('Missing command \'params\' field.') + + return cls(obj['name'], obj['params']) + + def serialize(self, view): + """ + Turn a command into a dictionary. + """ + return OrderedDict([ + ('name', self.name), + ('params', self.params), + ]) + + +class TeethAgentAPI(component.APIComponent): """ The primary Teeth Agent API. """ @@ -34,15 +57,25 @@ class TeethAgentAPI(APIComponent): Called during initialization. Override to map relative routes to methods. """ self.route('GET', '/status', self.get_agent_status) + self.route('POST', '/command', self.execute_agent_command) def get_agent_status(self, request): """ Get the status of the agent. """ - return ItemResponse(self.agent.get_status()) + return responses.ItemResponse(self.agent.get_status()) + + def execute_agent_command(self, request): + """ + Execute a command on the agent. + """ + command = AgentCommand.deserialize(self.parse_content(request)) + self.agent.execute_command(command) + # TODO(russellhaering): implement actual responses + return responses.ItemResponse({'result': 'success'}) -class TeethAgentAPIServer(APIServer): +class TeethAgentAPIServer(component.APIServer): """ Server for the teeth agent API. """