get things kind of working with pecan
This commit is contained in:
		@@ -1,5 +1,8 @@
 | 
			
		||||
Werkzeug==0.9.4
 | 
			
		||||
requests==2.0.0
 | 
			
		||||
cherrypy==3.2.4
 | 
			
		||||
stevedore==0.14
 | 
			
		||||
-e git+https://github.com/racker/teeth-rest.git@e876c0fddd5ce2f5223ab16936f711b0d57e19c4#egg=teeth_rest
 | 
			
		||||
wsgiref>=0.1.2
 | 
			
		||||
pecan>=0.4.5
 | 
			
		||||
oslo.config>=1.2.0
 | 
			
		||||
WSME>=0.6
 | 
			
		||||
 
 | 
			
		||||
@@ -19,14 +19,14 @@ import random
 | 
			
		||||
import threading
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from cherrypy import wsgiserver
 | 
			
		||||
import pkg_resources
 | 
			
		||||
from stevedore import driver
 | 
			
		||||
import structlog
 | 
			
		||||
from teeth_rest import encoding
 | 
			
		||||
from teeth_rest import errors as rest_errors
 | 
			
		||||
from wsgiref import simple_server
 | 
			
		||||
 | 
			
		||||
from teeth_agent import api
 | 
			
		||||
from teeth_agent.api import app
 | 
			
		||||
from teeth_agent import base
 | 
			
		||||
from teeth_agent import errors
 | 
			
		||||
from teeth_agent import hardware
 | 
			
		||||
@@ -112,7 +112,7 @@ class TeethAgent(object):
 | 
			
		||||
        self.listen_address = listen_address
 | 
			
		||||
        self.mode_implementation = None
 | 
			
		||||
        self.version = pkg_resources.get_distribution('teeth-agent').version
 | 
			
		||||
        self.api = api.TeethAgentAPIServer(self)
 | 
			
		||||
        self.api = app.VersionSelectorApplication()
 | 
			
		||||
        self.command_results = collections.OrderedDict()
 | 
			
		||||
        self.heartbeater = TeethAgentHeartbeater(self)
 | 
			
		||||
        self.hardware = hardware.get_manager()
 | 
			
		||||
@@ -196,13 +196,16 @@ class TeethAgent(object):
 | 
			
		||||
        """Run the Teeth Agent."""
 | 
			
		||||
        self.started_at = time.time()
 | 
			
		||||
        self.heartbeater.start()
 | 
			
		||||
        server = wsgiserver.CherryPyWSGIServer(self.listen_address, self.api)
 | 
			
		||||
        wsgi = simple_server.make_server(
 | 
			
		||||
            self.listen_address[0],
 | 
			
		||||
            self.listen_address[1],
 | 
			
		||||
            self.api,
 | 
			
		||||
            server_class=simple_server.WSGIServer)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            server.start()
 | 
			
		||||
            wsgi.serve_forever()
 | 
			
		||||
        except BaseException as e:
 | 
			
		||||
            self.log.error('shutting down', exception=e)
 | 
			
		||||
            server.stop()
 | 
			
		||||
 | 
			
		||||
        self.heartbeater.stop()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								teeth_agent/api/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								teeth_agent/api/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
"""
 | 
			
		||||
Copyright 2014 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.
 | 
			
		||||
"""
 | 
			
		||||
							
								
								
									
										66
									
								
								teeth_agent/api/app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								teeth_agent/api/app.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
"""
 | 
			
		||||
Copyright 2014 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.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from oslo.config import cfg
 | 
			
		||||
import pecan
 | 
			
		||||
 | 
			
		||||
from teeth_agent.api import config
 | 
			
		||||
 | 
			
		||||
CONF = cfg.CONF
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_pecan_config():
 | 
			
		||||
    # Set up the pecan configuration
 | 
			
		||||
    filename = config.__file__.replace('.pyc', '.py')
 | 
			
		||||
    return pecan.configuration.conf_from_file(filename)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def setup_app(pecan_config=None, extra_hooks=None):
 | 
			
		||||
    #policy.init()
 | 
			
		||||
 | 
			
		||||
    #app_hooks = [hooks.ConfigHook(),
 | 
			
		||||
                 #hooks.DBHook(),
 | 
			
		||||
                 #hooks.ContextHook(pecan_config.app.acl_public_routes),
 | 
			
		||||
                 #hooks.RPCHook(),
 | 
			
		||||
                 #hooks.NoExceptionTracebackHook()]
 | 
			
		||||
    #if extra_hooks:
 | 
			
		||||
        #app_hooks.extend(extra_hooks)
 | 
			
		||||
 | 
			
		||||
    if not pecan_config:
 | 
			
		||||
        pecan_config = get_pecan_config()
 | 
			
		||||
 | 
			
		||||
    pecan.configuration.set_config(dict(pecan_config), overwrite=True)
 | 
			
		||||
 | 
			
		||||
    app = pecan.make_app(
 | 
			
		||||
        pecan_config.app.root,
 | 
			
		||||
        static_root=pecan_config.app.static_root,
 | 
			
		||||
        debug=True,
 | 
			
		||||
        #debug=CONF.debug,
 | 
			
		||||
        force_canonical=getattr(pecan_config.app, 'force_canonical', True),
 | 
			
		||||
        #hooks=app_hooks,
 | 
			
		||||
        #wrap_app=middleware.ParsableErrorMiddleware,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    return app
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VersionSelectorApplication(object):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        pc = get_pecan_config()
 | 
			
		||||
        self.v1 = setup_app(pecan_config=pc)
 | 
			
		||||
 | 
			
		||||
    def __call__(self, environ, start_response):
 | 
			
		||||
        return self.v1(environ, start_response)
 | 
			
		||||
							
								
								
									
										0
									
								
								teeth_agent/api/app.wsgi
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								teeth_agent/api/app.wsgi
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										39
									
								
								teeth_agent/api/config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								teeth_agent/api/config.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
"""
 | 
			
		||||
Copyright 2014 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.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# Server Specific Configurations
 | 
			
		||||
# See https://pecan.readthedocs.org/en/latest/configuration.html#server-configuration # noqa
 | 
			
		||||
server = {
 | 
			
		||||
    'port': '9999',
 | 
			
		||||
    'host': '0.0.0.0'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Pecan Application Configurations
 | 
			
		||||
# See https://pecan.readthedocs.org/en/latest/configuration.html#application-configuration # noqa
 | 
			
		||||
app = {
 | 
			
		||||
    'root': 'teeth_agent.api.controllers.root.RootController',
 | 
			
		||||
    'modules': ['teeth_agent.api'],
 | 
			
		||||
    'static_root': '%(confdir)s/public',
 | 
			
		||||
    'debug': False,
 | 
			
		||||
    'enable_acl': True,
 | 
			
		||||
    'acl_public_routes': ['/', '/v1'],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# WSME Configurations
 | 
			
		||||
# See https://wsme.readthedocs.org/en/latest/integrate.html#configuration
 | 
			
		||||
wsme = {
 | 
			
		||||
    'debug': False,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								teeth_agent/api/controllers/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								teeth_agent/api/controllers/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
"""
 | 
			
		||||
Copyright 2014 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.
 | 
			
		||||
"""
 | 
			
		||||
							
								
								
									
										100
									
								
								teeth_agent/api/controllers/root.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								teeth_agent/api/controllers/root.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
# -*- encoding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
# Copyright © 2012 New Dream Network, LLC (DreamHost)
 | 
			
		||||
#
 | 
			
		||||
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
 | 
			
		||||
#
 | 
			
		||||
# 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 pecan
 | 
			
		||||
from pecan import rest
 | 
			
		||||
 | 
			
		||||
from wsme import types as wtypes
 | 
			
		||||
import wsmeext.pecan as wsme_pecan
 | 
			
		||||
 | 
			
		||||
from teeth_agent.api.controllers import v1
 | 
			
		||||
from teeth_agent.api.controllers.v1 import base
 | 
			
		||||
from teeth_agent.api.controllers.v1 import link
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Version(base.APIBase):
 | 
			
		||||
    """An API version representation."""
 | 
			
		||||
 | 
			
		||||
    id = wtypes.text
 | 
			
		||||
    "The ID of the version, also acts as the release number"
 | 
			
		||||
 | 
			
		||||
    links = [link.Link]
 | 
			
		||||
    "A Link that point to a specific version of the API"
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def convert(self, id):
 | 
			
		||||
        version = Version()
 | 
			
		||||
        version.id = id
 | 
			
		||||
        version.links = [link.Link.make_link('self', pecan.request.host_url,
 | 
			
		||||
                                             id, '', bookmark=True)]
 | 
			
		||||
        return version
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Root(base.APIBase):
 | 
			
		||||
 | 
			
		||||
    name = wtypes.text
 | 
			
		||||
    "The name of the API"
 | 
			
		||||
 | 
			
		||||
    description = wtypes.text
 | 
			
		||||
    "Some information about this API"
 | 
			
		||||
 | 
			
		||||
    versions = [Version]
 | 
			
		||||
    "Links to all the versions available in this API"
 | 
			
		||||
 | 
			
		||||
    default_version = Version
 | 
			
		||||
    "A link to the default version of the API"
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def convert(self):
 | 
			
		||||
        root = Root()
 | 
			
		||||
        root.name = "OpenStack Ironic API"
 | 
			
		||||
        root.description = ("Ironic is an OpenStack project which aims to "
 | 
			
		||||
                            "provision baremetal machines.")
 | 
			
		||||
        root.versions = [Version.convert('v1')]
 | 
			
		||||
        root.default_version = Version.convert('v1')
 | 
			
		||||
        return root
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RootController(rest.RestController):
 | 
			
		||||
 | 
			
		||||
    _versions = ['v1']
 | 
			
		||||
    "All supported API versions"
 | 
			
		||||
 | 
			
		||||
    _default_version = 'v1'
 | 
			
		||||
    "The default API version"
 | 
			
		||||
 | 
			
		||||
    v1 = v1.Controller()
 | 
			
		||||
 | 
			
		||||
    @wsme_pecan.wsexpose(Root)
 | 
			
		||||
    def get(self):
 | 
			
		||||
        # NOTE: The reason why convert() it's being called for every
 | 
			
		||||
        #       request is because we need to get the host url from
 | 
			
		||||
        #       the request object to make the links.
 | 
			
		||||
        return Root.convert()
 | 
			
		||||
 | 
			
		||||
    @pecan.expose()
 | 
			
		||||
    def _route(self, args):
 | 
			
		||||
        """Overrides the default routing behavior.
 | 
			
		||||
 | 
			
		||||
        It redirects the request to the default version of the ironic API
 | 
			
		||||
        if the version number is not specified in the url.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        if args[0] and args[0] not in self._versions:
 | 
			
		||||
            args = [self._default_version] + args
 | 
			
		||||
        return super(RootController, self)._route(args)
 | 
			
		||||
							
								
								
									
										135
									
								
								teeth_agent/api/controllers/v1/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								teeth_agent/api/controllers/v1/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
# All Rights Reserved.
 | 
			
		||||
#
 | 
			
		||||
#    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.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Version 1 of the Ironic API
 | 
			
		||||
 | 
			
		||||
NOTE: IN PROGRESS AND NOT FULLY IMPLEMENTED.
 | 
			
		||||
 | 
			
		||||
Should maintain feature parity with Nova Baremetal Extension.
 | 
			
		||||
 | 
			
		||||
Specification can be found at ironic/doc/api/v1.rst
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import pecan
 | 
			
		||||
from pecan import rest
 | 
			
		||||
 | 
			
		||||
from wsme import types as wtypes
 | 
			
		||||
import wsmeext.pecan as wsme_pecan
 | 
			
		||||
 | 
			
		||||
from teeth_agent.api.controllers.v1 import base
 | 
			
		||||
#from ironic.api.controllers.v1 import chassis
 | 
			
		||||
#from ironic.api.controllers.v1 import driver
 | 
			
		||||
from teeth_agent.api.controllers.v1 import link
 | 
			
		||||
#from ironic.api.controllers.v1 import node
 | 
			
		||||
#from ironic.api.controllers.v1 import port
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MediaType(base.APIBase):
 | 
			
		||||
    """A media type representation."""
 | 
			
		||||
 | 
			
		||||
    base = wtypes.text
 | 
			
		||||
    type = wtypes.text
 | 
			
		||||
 | 
			
		||||
    def __init__(self, base, type):
 | 
			
		||||
        self.base = base
 | 
			
		||||
        self.type = type
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class V1(base.APIBase):
 | 
			
		||||
    """The representation of the version 1 of the API."""
 | 
			
		||||
 | 
			
		||||
    id = wtypes.text
 | 
			
		||||
    "The ID of the version, also acts as the release number"
 | 
			
		||||
 | 
			
		||||
    media_types = [MediaType]
 | 
			
		||||
    "An array of supported media types for this version"
 | 
			
		||||
 | 
			
		||||
    links = [link.Link]
 | 
			
		||||
    "Links that point to a specific URL for this version and documentation"
 | 
			
		||||
 | 
			
		||||
    #chassis = [link.Link]
 | 
			
		||||
    #"Links to the chassis resource"
 | 
			
		||||
 | 
			
		||||
    #nodes = [link.Link]
 | 
			
		||||
    #"Links to the nodes resource"
 | 
			
		||||
 | 
			
		||||
    #ports = [link.Link]
 | 
			
		||||
    #"Links to the ports resource"
 | 
			
		||||
 | 
			
		||||
    #drivers = [link.Link]
 | 
			
		||||
    #"Links to the drivers resource"
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def convert(self):
 | 
			
		||||
        v1 = V1()
 | 
			
		||||
        v1.id = "v1"
 | 
			
		||||
        v1.links = [
 | 
			
		||||
            link.Link.make_link('self', pecan.request.host_url,
 | 
			
		||||
                                'v1', '', bookmark=True),
 | 
			
		||||
            link.Link.make_link('describedby',
 | 
			
		||||
                                'http://docs.openstack.org',
 | 
			
		||||
                                'developer/ironic/dev',
 | 
			
		||||
                                'api-spec-v1.html',
 | 
			
		||||
                                bookmark=True, type='text/html')
 | 
			
		||||
        ]
 | 
			
		||||
        v1.media_types = [MediaType('application/json',
 | 
			
		||||
                          'application/vnd.openstack.ironic.v1+json')]
 | 
			
		||||
        #v1.chassis = [link.Link.make_link('self', pecan.request.host_url,
 | 
			
		||||
                                          #'chassis', ''),
 | 
			
		||||
                      #link.Link.make_link('bookmark',
 | 
			
		||||
                                           #pecan.request.host_url,
 | 
			
		||||
                                           #'chassis', '',
 | 
			
		||||
                                           #bookmark=True)
 | 
			
		||||
                     #]
 | 
			
		||||
        #v1.nodes = [link.Link.make_link('self', pecan.request.host_url,
 | 
			
		||||
                                        #'nodes', ''),
 | 
			
		||||
                    #link.Link.make_link('bookmark',
 | 
			
		||||
                                        #pecan.request.host_url,
 | 
			
		||||
                                        #'nodes', '',
 | 
			
		||||
                                        #bookmark=True)
 | 
			
		||||
                   #]
 | 
			
		||||
        #v1.ports = [link.Link.make_link('self', pecan.request.host_url,
 | 
			
		||||
                                        #'ports', ''),
 | 
			
		||||
                    #link.Link.make_link('bookmark',
 | 
			
		||||
                                        #pecan.request.host_url,
 | 
			
		||||
                                        #'ports', '',
 | 
			
		||||
                                        #bookmark=True)
 | 
			
		||||
                   #]
 | 
			
		||||
        #v1.drivers = [link.Link.make_link('self', pecan.request.host_url,
 | 
			
		||||
                                          #'drivers', ''),
 | 
			
		||||
                      #link.Link.make_link('bookmark',
 | 
			
		||||
                                          #pecan.request.host_url,
 | 
			
		||||
                                          #'drivers', '',
 | 
			
		||||
                                          #bookmark=True)
 | 
			
		||||
                     #]
 | 
			
		||||
        return v1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Controller(rest.RestController):
 | 
			
		||||
    """Version 1 API controller root."""
 | 
			
		||||
 | 
			
		||||
    #nodes = node.NodesController()
 | 
			
		||||
    #ports = port.PortsController()
 | 
			
		||||
    #chassis = chassis.ChassisController()
 | 
			
		||||
    #drivers = driver.DriversController()
 | 
			
		||||
 | 
			
		||||
    @wsme_pecan.wsexpose(V1)
 | 
			
		||||
    def get(self):
 | 
			
		||||
        # NOTE: The reason why convert() it's being called for every
 | 
			
		||||
        #       request is because we need to get the host url from
 | 
			
		||||
        #       the request object to make the links.
 | 
			
		||||
        return V1.convert()
 | 
			
		||||
 | 
			
		||||
__all__ = (Controller)
 | 
			
		||||
							
								
								
									
										47
									
								
								teeth_agent/api/controllers/v1/base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								teeth_agent/api/controllers/v1/base.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
# All Rights Reserved.
 | 
			
		||||
#
 | 
			
		||||
#    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 datetime
 | 
			
		||||
 | 
			
		||||
import wsme
 | 
			
		||||
from wsme import types as wtypes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class APIBase(wtypes.Base):
 | 
			
		||||
 | 
			
		||||
    created_at = wsme.wsattr(datetime.datetime, readonly=True)
 | 
			
		||||
    "The time in UTC at which the object is created"
 | 
			
		||||
 | 
			
		||||
    updated_at = wsme.wsattr(datetime.datetime, readonly=True)
 | 
			
		||||
    "The time in UTC at which the object is updated"
 | 
			
		||||
 | 
			
		||||
    def as_dict(self):
 | 
			
		||||
        """Render this object as a dict of its fields."""
 | 
			
		||||
        return dict((k, getattr(self, k))
 | 
			
		||||
                    for k in self.fields
 | 
			
		||||
                    if hasattr(self, k) and
 | 
			
		||||
                    getattr(self, k) != wsme.Unset)
 | 
			
		||||
 | 
			
		||||
    def unset_fields_except(self, except_list=None):
 | 
			
		||||
        """Unset fields so they don't appear in the message body.
 | 
			
		||||
 | 
			
		||||
        :param except_list: A list of fields that won't be touched.
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        if except_list is None:
 | 
			
		||||
            except_list = []
 | 
			
		||||
 | 
			
		||||
        for k in self.as_dict():
 | 
			
		||||
            if k not in except_list:
 | 
			
		||||
                setattr(self, k, wsme.Unset)
 | 
			
		||||
							
								
								
									
										43
									
								
								teeth_agent/api/controllers/v1/link.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								teeth_agent/api/controllers/v1/link.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
# Copyright 2013 Red Hat, Inc.
 | 
			
		||||
# All Rights Reserved.
 | 
			
		||||
#
 | 
			
		||||
#    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.
 | 
			
		||||
 | 
			
		||||
from wsme import types as wtypes
 | 
			
		||||
 | 
			
		||||
from teeth_agent.api.controllers.v1 import base
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Link(base.APIBase):
 | 
			
		||||
    """A link representation."""
 | 
			
		||||
 | 
			
		||||
    href = wtypes.text
 | 
			
		||||
    "The url of a link."
 | 
			
		||||
 | 
			
		||||
    rel = wtypes.text
 | 
			
		||||
    "The name of a link."
 | 
			
		||||
 | 
			
		||||
    type = wtypes.text
 | 
			
		||||
    "Indicates the type of document/link."
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def make_link(cls, rel_name, url, resource, resource_args,
 | 
			
		||||
                  bookmark=False, type=wtypes.Unset):
 | 
			
		||||
        template = '%s/%s' if bookmark else '%s/v1/%s'
 | 
			
		||||
        # FIXME(lucasagomes): I'm getting a 404 when doing a GET on
 | 
			
		||||
        # a nested resource that the URL ends with a  '/'.
 | 
			
		||||
        # https://groups.google.com/forum/#!topic/pecan-dev/QfSeviLg5qs
 | 
			
		||||
        template += '%s' if resource_args.startswith('?') else '/%s'
 | 
			
		||||
 | 
			
		||||
        return Link(href=(template) % (url, resource, resource_args),
 | 
			
		||||
                    rel=rel_name, type=type)
 | 
			
		||||
@@ -20,6 +20,7 @@ import unittest
 | 
			
		||||
 | 
			
		||||
import mock
 | 
			
		||||
import pkg_resources
 | 
			
		||||
from wsgiref import simple_server
 | 
			
		||||
 | 
			
		||||
from teeth_rest import encoding
 | 
			
		||||
 | 
			
		||||
@@ -156,7 +157,7 @@ class TestBaseAgent(unittest.TestCase):
 | 
			
		||||
                          'do_something',
 | 
			
		||||
                          foo='bar')
 | 
			
		||||
 | 
			
		||||
    @mock.patch('cherrypy.wsgiserver.CherryPyWSGIServer', autospec=True)
 | 
			
		||||
    @mock.patch('wsgiref.simple_server.make_server', autospec=True)
 | 
			
		||||
    def test_run(self, wsgi_server_cls):
 | 
			
		||||
        wsgi_server = wsgi_server_cls.return_value
 | 
			
		||||
        wsgi_server.start.side_effect = KeyboardInterrupt()
 | 
			
		||||
@@ -165,9 +166,12 @@ class TestBaseAgent(unittest.TestCase):
 | 
			
		||||
        self.agent.run()
 | 
			
		||||
 | 
			
		||||
        listen_addr = ('localhost', 9999)
 | 
			
		||||
        wsgi_server_cls.assert_called_once_with(listen_addr, self.agent.api)
 | 
			
		||||
        wsgi_server.start.assert_called_once_with()
 | 
			
		||||
        wsgi_server.stop.assert_called_once_with()
 | 
			
		||||
        wsgi_server_cls.assert_called_once_with(
 | 
			
		||||
            listen_addr[0],
 | 
			
		||||
            listen_addr[1],
 | 
			
		||||
            self.agent.api,
 | 
			
		||||
            server_class=simple_server.WSGIServer)
 | 
			
		||||
        wsgi_server.serve_forever.assert_called_once_with()
 | 
			
		||||
 | 
			
		||||
        self.agent.heartbeater.start.assert_called_once_with()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user