Exemplo n.º 1
0
    def __init__(self, registry=None):

        if registry is None:
            self.registry = NonePersistentRegistry()
        elif isinstance(registry, Registry):
            self.registry = registry
        else:
            raise AttributeError('Registry needs to derive from abstract' \
                                 ' class \'Registry\'')

        self.registry.set_renderer('text/occi',
                                   TextOcciRendering(self.registry))
        self.registry.set_renderer('text/plain',
                                   TextPlainRendering(self.registry))
        self.registry.set_renderer('text/uri-list',
                                   TextUriListRendering(self.registry))
        self.registry.set_renderer('text/html', HTMLRendering(self.registry))

        application = tornado.web.Application([
            (r"/-/", QueryHandler, dict(registry=self.registry)),
            (r"/.well-known/org/ogf/occi/-/", QueryHandler,
             dict(registry=self.registry)),
            (r"(.*)/", CollectionHandler, dict(registry=self.registry)),
            (r"(.*)", ResourceHandler, dict(registry=self.registry)),
        ])

        self.http_server = tornado.httpserver.HTTPServer(application)
Exemplo n.º 2
0
class TestTextURIListRendering(unittest.TestCase):
    '''
    Test the uri-list rendering.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.rendering = TextUriListRendering(self.registry)

    def test_from_entities_for_sanity(self):
        '''
        Test uri listings...
        '''
        res = Resource('/foo/123', None, [])
        entities = [res]
        heads, body = self.rendering.from_entities(entities, 'foo')
        self.assertTrue(heads == {})
        self.assertTrue(res.identifier in body)

    def test_not_support_thrown_for_success(self):
        '''
        Tests is attr-exp are thrown for unsupported operations.
        '''
        self.assertRaises(AttributeError, self.rendering.to_entity, None, None,
                          None)
        self.assertRaises(AttributeError, self.rendering.from_entity, None)
        self.assertRaises(AttributeError, self.rendering.to_entities, None,
                          None)
        self.assertRaises(AttributeError, self.rendering.from_categories, None)
        self.assertRaises(AttributeError, self.rendering.to_action, None, None)
        self.assertRaises(AttributeError, self.rendering.to_mixins, None, None)
        self.assertRaises(AttributeError, self.rendering.get_filters, None,
                          None)
Exemplo n.º 3
0
class TestTextPlainRendering(unittest.TestCase):
    '''
    Test the text / plain rendering. This is simple since it's derived from
    text/occi rendering.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.rendering = TextPlainRendering(self.registry)

    def test_data_routines_for_sanity(self):
        '''
        Test if set and get data are overwritten and work properly
        '''
        headers = {}
        body = 'Category: foo\n' \
            'Category: foo,bar\n' \
            'Link: bar\n' \
            'Link: foo,bar\n' \
            'X-OCCI-Location: foo,bar\n' \
            'X-OCCI-Location: bar\n' \
            'X-OCCI-Attribute: foo\n' \
            'X-OCCI-Attribute: bar,foo\n'
        data = self.rendering.get_data(headers, body)
        headers, body = self.rendering.set_data(data)
        self.assertTrue(body.count('Category') == 3)
        self.assertTrue(body.count('Link') == 3)
        self.assertTrue(body.count('X-OCCI-Attribute') == 3)
        self.assertTrue(body.count('X-OCCI-Location') == 3)
Exemplo n.º 4
0
class CategoryRegistryTest(unittest.TestCase):
    '''
    Test the capabilities to retrieve categories.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.kind1 = Kind('http://example.com#', '1')
        self.kind2 = Kind('http://example.com#', '2', location='/foo/')

        self.registry.set_backend(self.kind1, KindBackend())
        self.registry.set_backend(self.kind2, DummyBackend())

    def tearDown(self):
        for item in self.registry.get_categories():
            self.registry.delete_mixin(item)

    def test_get_category_for_sanity(self):
        '''
        Test if the category can be retrieved from a URN.
        '''
        result = self.registry.get_category('/1/')
        self.assertTrue(self.kind1 == result)

        result = self.registry.get_category('/foo/')
        self.assertTrue(self.kind2 == result)

        result = self.registry.get_category('/bar/')
        self.assertTrue(result == None)
Exemplo n.º 5
0
    def __init__(self, registry=None):

        if registry is None:
            self.registry = NonePersistentRegistry()
        elif isinstance(registry, Registry):
            self.registry = registry
        else:
            raise AttributeError('Registry needs to derive from abstract' \
                                 ' class \'Registry\'')

        self.registry.set_renderer('text/occi',
                                   TextOcciRendering(self.registry))
        self.registry.set_renderer('text/plain',
                                   TextPlainRendering(self.registry))
        self.registry.set_renderer('text/uri-list',
                                   TextUriListRendering(self.registry))
        self.registry.set_renderer('text/html', HTMLRendering(self.registry))

        application = tornado.web.Application([
                (r"/-/", QueryHandler, dict(registry=self.registry)),
                (r"/.well-known/org/ogf/occi/-/",
                 QueryHandler,
                 dict(registry=self.registry)),
                (r"(.*)/", CollectionHandler, dict(registry=self.registry)),
                (r"(.*)", ResourceHandler, dict(registry=self.registry)),
            ])

        self.http_server = tornado.httpserver.HTTPServer(application)
 def test_init_for_success(self):
     '''
     Test init...
     '''
     parser = HTMLRendering(NonePersistentRegistry(),
                            css='body {background: #d00;}')
     self.assertEquals(parser.css, 'body {background: #d00;}')
Exemplo n.º 7
0
class TestService(unittest.TestCase):
    '''
    Test the service extension point.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.service = OCCI()

    def test_init_for_sanity(self):
        '''
        Test constructor and initialization of service.
        '''
        self.assertTrue(self.registry.get_renderer('text/occi'))
        self.assertTrue(self.registry.get_renderer('text/plain'))
        self.assertTrue(self.registry.get_renderer('text/uri-list'))
        self.assertTrue(self.registry.get_renderer('text/html'))

        OCCI(registry=NonePersistentRegistry())

    def test_register_backend_for_failure(self):
        '''
        Test registration.
        '''
        back = ActionBackend()
        self.assertRaises(AttributeError, self.service.register_backend,
                          COMPUTE, back)
        try:
            OCCI(registry=dict())
        except AttributeError:
            pass
        else:
            self.assertFalse(True, 'Exception not thrown...')

    def test_register_backend_for_sanity(self):
        '''
        Test registration.
        '''
        back = KindBackend()
        back1 = MixinBackend()
        back2 = ActionBackend()
        self.service.register_backend(COMPUTE, back)
        self.service.register_backend(IPNETWORKINTERFACE, back1)
        self.service.register_backend(START, back2)

        self.assertTrue(self.registry.get_backend(COMPUTE) == back)
        self.assertTrue(self.registry.get_backend(IPNETWORKINTERFACE) == back1)
        self.assertTrue(self.registry.get_backend(START) == back2)

    def test_start_for_success(self):
        '''
        Just here to reach 100% code coverage :-)
        '''
        self.service.http_server.listen = fake_listen
        tornado.ioloop.IOLoop.instance = fake_ioloop
        self.service.start(1010)
Exemplo n.º 8
0
    def __init__(self, application, request, **kwargs):
        super(BaseHandler, self).__init__(application, request, **kwargs)
        # This ensures that at least one registry is loaded in case initialize
        # is not called for some reason...
        self.registry = NonePersistentRegistry()

        if self.registry.get_hostname() == '':
            self.registry.set_hostname(self.request.protocol + '://' +
                                       self.request.host)
Exemplo n.º 9
0
    def test_init_for_sanity(self):
        '''
        Test constructor and initialization of service.
        '''
        self.assertTrue(self.registry.get_renderer('text/occi'))
        self.assertTrue(self.registry.get_renderer('text/plain'))
        self.assertTrue(self.registry.get_renderer('text/uri-list'))
        self.assertTrue(self.registry.get_renderer('text/html'))

        OCCI(registry=NonePersistentRegistry())
class TestHTMLRendering(unittest.TestCase):
    '''
    Just some simple calls on the HTML rendering.
    '''

    parser = HTMLRendering(NonePersistentRegistry())

    def setUp(self):
        action = Action('http://example.com/foo#', 'action')
        self.kind = Kind('http://example.com/foo#', 'bar',
                         'http://schemeas.ogf.org/occi/core#',
                          [action], 'Some bla bla',
                          {'foo': 'required', 'foo2': 'immutable', 'bar': ''},
                          '/foo/')
        mixin = Mixin('http://example.com/foo#', 'mixin')
        action = Action('http://example.com/foo#', 'action')
        self.target = Resource('/foo/target', self.kind, [], [])
        self.source = Resource('/foo/src', self.kind, [mixin], [])
        self.link = Link('/link/foo', self.kind, [], self.source, self.target)
        self.source.links = [self.link]
        self.source.actions = [action]

    #==========================================================================
    # Success
    #==========================================================================

    def test_init_for_success(self):
        '''
        Test init...
        '''
        parser = HTMLRendering(NonePersistentRegistry(),
                               css='body {background: #d00;}')
        self.assertEquals(parser.css, 'body {background: #d00;}')

    def test_from_entity_for_success(self):
        '''
        Test from entity...
        '''
        self.parser.from_entity(self.source)
        self.parser.from_entity(self.link)

    def test_from_entities_for_success(self):
        '''
        Test from entities...
        '''
        self.parser.from_entities([self.source], '/foo/')
        self.parser.from_entities([], '/')

    def test_from_categories_for_success(self):
        '''
        Test from categories...
        '''
        self.parser.from_categories([self.kind])
Exemplo n.º 11
0
class TestParserRegistry(unittest.TestCase):
    '''
    Test if parser can be found...
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.registry.set_renderer('text/plain', DummyRendering(self.registry))
        self.registry.set_renderer('text/occi', DummyRendering(self.registry))

    def tearDown(self):
        for item in self.registry.get_categories():
            self.registry.delete_mixin(item)

    def test_get_parser_for_success(self):
        '''
        Test retrieval of parsers.
        '''
        self.registry.get_renderer('text/plain')
        self.registry.get_renderer('text/occi')

    def test_get_parser_for_failure(self):
        '''
        Test failure handling of retrieval.
        '''
        self.assertRaises(HTTPError, self.registry.get_renderer, 'foo')

    def test_set_parser_for_failure(self):
        '''
        Test failure handling of setting a renderer.
        '''
        self.assertRaises(AttributeError, self.registry.set_renderer, 'foo',
                          None)

    def test_get_parser_for_sanity(self):
        '''
        Some sanity checks.
        '''
        parser1 = self.registry.get_renderer('text/plain')
        parser2 = self.registry.get_renderer('text/plain;q=0.9')
        parser3 = self.registry.get_renderer('*/*')

        self.assertEquals(parser1, parser3)
        self.assertEquals(parser2, parser3)
Exemplo n.º 12
0
class TestMisc(unittest.TestCase):
    '''
    Several other tests...
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.app = Application([(r"(.*)", ResourceWrapper)])

    def test_get_error_html_for_success(self):
        '''
        Test retrieval of Error codes...
        '''
        handler = BaseHandler(self.app,
                              create_request('GET', {}, ''),
                              registry=self.registry)
        handler.get_error_html(200)
Exemplo n.º 13
0
class ResourcesTest(unittest.TestCase):
    '''
    Tests the reigstry's resource handling.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.res1 = Resource('foo', None, None)
        self.res2 = Resource('bar', None, None)

    def tearDown(self):
        for resource in self.registry.get_resources():
            self.registry.delete_resource(resource.identifier)

    def test_get_resource_for_sanity(self):
        '''
        Test if added resource can be retrieved.
        '''
        self.registry.add_resource('foo', self.res1)
        self.assertEquals(self.res1, self.registry.get_resource('foo'))

    def test_delete_resource_for_sanity(self):
        '''
        Test if delete resource cannot be retrieved.
        '''
        self.registry.add_resource('foo', self.res1)
        self.registry.delete_resource('foo')
        self.assertRaises(KeyError, self.registry.get_resource, 'foo')

    def test_resources_for_sanity(self):
        '''
        Test is all resources and all keys can be retrieved.
        '''
        self.registry.add_resource('foo', self.res1)
        self.registry.add_resource('bar', self.res2)
        self.assertTrue(len(self.registry.get_resources()) == 2)
        self.assertTrue(len(self.registry.get_resource_keys()) == 2)
Exemplo n.º 14
0
class TestRendering(unittest.TestCase):
    '''
    Test for the abstract Rendering class.
    '''

    registry = NonePersistentRegistry()

    def test_if_not_implemented_is_thrown(self):
        '''
        Just to check the abstract class.
        '''
        rendering = Rendering(self.registry)
        self.assertRaises(NotImplementedError, rendering.to_entity, None, None,
                          None)
        self.assertRaises(NotImplementedError, rendering.to_action, None, None)
        self.assertRaises(NotImplementedError, rendering.to_entities, None,
                          None)
        self.assertRaises(NotImplementedError, rendering.to_mixins, None, None)
        self.assertRaises(NotImplementedError, rendering.get_filters, None,
                          None)
        self.assertRaises(NotImplementedError, rendering.from_entity, None)
        self.assertRaises(NotImplementedError, rendering.from_categories, None)
        self.assertRaises(NotImplementedError, rendering.from_entities, None,
                          None)
Exemplo n.º 15
0
class TestCollectionCapabilites(unittest.TestCase):
    '''
    Test the collection handler.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.registry.set_hostname('http://127.0.0.1')
        self.app = Application([(r"(.*)/", CollectionWrapper)])

        self.registry.set_renderer('text/plain',
                                   TextPlainRendering(self.registry))
        self.registry.set_renderer('text/occi',
                                   TextOcciRendering(self.registry))
        self.registry.set_renderer('text/uri-list',
                                   TextUriListRendering(self.registry))

        self.mixin = Mixin('foo', 'mystuff')

        self.compute = Resource('/compute/1', COMPUTE, [])
        self.compute.attributes = {'foo2': 'bar2'}
        self.network = Resource('/network/1', NETWORK, [IPNETWORK])
        self.network_interface = Link('/network/interface/1', NETWORKINTERFACE,
                                      [IPNETWORKINTERFACE], self.compute,
                                      self.network)

        self.registry.set_backend(COMPUTE, SimpleComputeBackend())
        self.registry.set_backend(NETWORK, KindBackend())
        self.registry.set_backend(self.mixin, MixinBackend())
        self.registry.set_backend(START, SimpleComputeBackend())

        self.registry.add_resource(self.compute.identifier, self.compute)
        self.registry.add_resource(self.network.identifier, self.network)
        self.registry.add_resource(self.network_interface.identifier,
                                   self.network_interface)

    def tearDown(self):
        for item in self.registry.get_resources():
            self.registry.delete_resource(item.identifier)

    #==========================================================================
    # Failure
    #==========================================================================

    def test_retrieve_for_failure(self):
        '''
        Do a get with garbeage as filter...
        '''
        headers = {'Content-Type': 'text/occi', 'Category': 'asdf'}
        request = create_request('GET', headers, '')
        handler = CollectionWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.get, '')

    def test_action_for_failure(self):
        '''
        Tests if actions can be triggered with garbage as content
        '''
        headers = {'Content-Type': 'text/occi', 'Category': 'foobar'}
        request = create_request('POST', headers, '', '/compute/?action=start')
        handler = CollectionWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post, '')

    def test_update_mixin_collection_for_failure(self):
        '''
        Add mixins to resources.
        '''
        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Location': self.compute.identifier
        }
        request = create_request('POST', headers, '')
        handler = CollectionWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post, '/bla')

    def test_remove_entities_from_collection_for_failure(self):
        '''
        Add mixins to resources.
        '''
        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Location': self.compute.identifier
        }
        request = create_request('DELETE', headers, '')
        handler = CollectionWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.delete, '/bla/')

        headers = {
            'Content-Type': 'text/xml',
            'X-Occi-Location': self.compute.identifier
        }
        request = create_request('DELETE', headers, '')
        handler = CollectionWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.delete, '/bla/')

    def test_replace_mixin_collection_for_failure(self):
        '''
        Add mixins to resources.
        '''
        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Location': self.network.identifier
        }
        request = create_request('PUT', headers, '')
        handler = CollectionWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.put, '/bla')

    def test_create_entity_for_failure(self):
        '''
        Simple test - more complex one in TestResourceHandler...
        '''
        headers = {
            'Content-Type': 'text/xml',
            'Categories': parser.get_category_str(COMPUTE)
        }
        request = create_request('POST', headers, '')
        handler = CollectionWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post, '/compute')

        headers = {
            'Content-Type': 'text/occi',
            'Categories': parser.get_category_str(COMPUTE)
        }
        request = create_request('POST', headers, '')
        handler = CollectionWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post, '/compute')

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_retrieve_state_of_ns_for_sanity(self):
        '''
        Test GET with uri-list
        '''
        headers = {'Accept': 'text/uri-list'}
        request = create_request('GET', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.get('')
        headers, body = handler.get_output()
        self.assertTrue(headers['Content-Type'] == 'text/uri-list')
        self.assertTrue(len(body) == 98)

    def test_retrieve_for_sanity(self):
        '''
        Test GET with uri-list
        '''
        headers = {'Accept': 'text/occi'}
        request = create_request('GET', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.get('/compute/')
        headers, body = handler.get_output()
        self.assertTrue(headers['Content-Type'] == 'text/occi')
        self.assertTrue(self.compute.identifier in headers['X-OCCI-Location'])

        # filter on category
        headers = {
            'Accept': 'text/occi',
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(self.compute.kind)
        }
        request = create_request('GET', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.get('/')
        headers, body = handler.get_output()
        self.assertTrue(headers['Content-Type'] == 'text/occi')
        self.assertTrue(self.compute.identifier in headers['X-OCCI-Location'])
        self.assertFalse(self.network.identifier in headers['X-OCCI-Location'])

        # filter on attr...
        headers = {
            'Accept': 'text/occi',
            'Content-Type': 'text/occi',
            'X-Occi-Attribute': 'foo2="bar2"'
        }
        request = create_request('GET', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.get('/')
        headers, body = handler.get_output()
        self.assertTrue(headers['Content-Type'] == 'text/occi')
        self.assertTrue(self.compute.identifier in headers['X-OCCI-Location'])
        self.assertFalse(self.network.identifier in headers['X-OCCI-Location'])

    def test_delete_for_sanity(self):
        '''
        Tests if complete resource collection can be removed.
        '''
        request = create_request('DELETE', {}, '')
        handler = CollectionWrapper(self.app, request)
        handler.delete('/compute')
        self.assertFalse(self.compute in self.registry.get_resources())

    def test_action_for_sanity(self):
        '''
        Tests if actions can be triggered on a resource set.
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(START)
        }
        request = create_request('POST', headers, '', '/compute/?action=start')
        handler = CollectionWrapper(self.app, request)
        handler.post('/compute/')
        self.assertTrue(
            self.compute.attributes['occi.compute.state'] == 'active')

    def test_update_mixin_collection_for_sanity(self):
        '''
        Add mixins to resources.
        '''
        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Location': self.compute.identifier
        }
        request = create_request('POST', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.post('/mystuff/')
        self.assertTrue(self.mixin in self.compute.mixins)

    def test_remove_entities_from_collection_for_sanity(self):
        '''
        Add mixins to resources.
        '''
        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Location': self.compute.identifier
        }
        request = create_request('POST', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.post('/mystuff/')

        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Location': self.compute.identifier
        }
        request = create_request('DELETE', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.delete('/mystuff/')
        self.assertTrue(self.mixin not in self.compute.mixins)

    def test_replace_mixin_collection_for_sanity(self):
        '''
        Add mixins to resources.
        '''
        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Location': self.compute.identifier
        }
        request = create_request('POST', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.post('/mystuff/')

        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Location': self.network.identifier
        }
        request = create_request('PUT', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.put('/mystuff/')
        self.assertTrue(self.mixin not in self.compute.mixins)
        self.assertTrue(self.mixin in self.network.mixins)

    def test_create_entity_for_sanity(self):
        '''
        Simple test - more complex one in TestResourceHandler...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE)
        }
        request = create_request('POST', headers, '')
        handler = CollectionWrapper(self.app, request)
        handler.post('/compute/')
        self.assertTrue(len(self.registry.get_resources()) == 4)
Exemplo n.º 16
0
class TestBackendsRegistry(unittest.TestCase):
    '''
    Test for the registry.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.kind1 = Kind('http://example.com#', '1')
        self.kind2 = Kind('http://example.com#', '2')
        self.action = Action('http://example.com#', 'action')
        self.mixin = Mixin('http://example.com#', 'mixin')

        self.registry.set_backend(self.kind1, KindBackend())
        self.registry.set_backend(self.kind2, DummyBackend())
        self.registry.set_backend(self.action, ActionBackend())
        self.registry.set_backend(self.mixin, MixinBackend())

        self.entity = Resource('foo', self.kind1, [self.kind2])

    def tearDown(self):
        for item in self.registry.get_categories():
            self.registry.delete_mixin(item)

    #==========================================================================
    # Success
    #==========================================================================

    def test_get_backend_for_success(self):
        '''
        Test if backend can be retrieved...
        '''
        self.registry.get_backend(self.kind1)
        self.registry.get_backend(self.kind2)
        self.registry.get_backend(self.action)
        self.registry.get_backend(self.mixin)

    #==========================================================================
    # Failure
    #==========================================================================

    def test_get_backend_for_failure(self):
        '''
        Test if backend can be retrieved...
        '''
        self.assertRaises(AttributeError, self.registry.get_backend,
                          Kind('foo', 'bar'))

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_get_backend_for_sanity(self):
        '''
        Test if backend can be retrieved...
        '''
        back1 = self.registry.get_backend(self.kind1)
        back2 = self.registry.get_backend(self.kind2)
        self.assertTrue(isinstance(back1, KindBackend))
        self.assertTrue(isinstance(back2, DummyBackend))

    def test_get_all_backends_for_sanity(self):
        '''
        Test if all backends can be retrieved...
        '''
        backs = self.registry.get_all_backends(self.entity)
        self.assertTrue(len(backs) == 2)
Exemplo n.º 17
0
class CollectionWorkflowTest(unittest.TestCase):
    '''
    Test the workflow on operations on collections...
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.kind = Kind('http://example.com/foo#', 'bar')
        self.link_kind = Kind('http://example.com/foo#', 'link')
        self.mixin = Mixin('http://example.com/foo#', 'mixin')

        target = Resource('/foo/target', self.kind, [], [])

        source = Resource('/foo/src', self.kind, [self.mixin], [])
        source.attributes = {'foo': 'bar'}

        link = Link('/link/foo', self.link_kind, [], source, target)
        link.attributes = {'foo': 'bar'}
        source.links = [link]

        self.resources = [source, target, link]
        for item in self.resources:
            self.registry.add_resource(item.identifier, item)

        self.registry.set_backend(self.kind, KindBackend())
        self.registry.set_backend(self.mixin, MixinBackend())

    def tearDown(self):
        for item in self.registry.get_resources():
            self.registry.delete_resource(item.identifier)
        for item in self.registry.get_categories():
            self.registry.delete_mixin(item)

    #==========================================================================
    # Success
    #==========================================================================

    def test_get_entities_for_success(self):
        '''
        Tests retrieval of resources.
        '''
        lst = workflow.get_entities_under_path('/', self.registry)
        self.assertTrue(self.resources[0] in lst)

    def test_filter_entities_for_success(self):
        '''
        Call the filter test.
        '''
        workflow.filter_entities(self.resources, [], {})
        workflow.filter_entities(self.resources, [self.kind], {})
        workflow.filter_entities(self.resources, [], {'foo': 'bar'})

    #==========================================================================
    # Failure
    #==========================================================================

    def test_update_collection_for_failure(self):
        '''
        Check if the update functionalities are implemented correctly.
        '''
        self.assertRaises(AttributeError, workflow.update_collection,
                          self.kind, [], [], self.registry)

    def test_replace_collection_for_failure(self):
        '''
        Check if the replace functionalities are implemented correctly.
        '''
        self.assertRaises(AttributeError, workflow.replace_collection,
                          self.kind, [], [], self.registry)

    def test_delete_from_collection_for_failure(self):
        '''
        Check if the delete functionalities are implemented correctly.
        '''
        self.assertRaises(AttributeError, workflow.delete_from_collection,
                          self.kind, [], self.registry)

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_get_entities_for_sanity(self):
        '''
        Test if correct entities are returned.
        '''
        lst = workflow.get_entities_under_path('/link/', self.registry)
        self.assertTrue(self.resources[2] in lst)
        self.assertTrue(len(lst) == 1)

        lst = workflow.get_entities_under_path('/bar/', self.registry)
        self.assertTrue(self.resources[0] in lst)
        self.assertTrue(self.resources[1] in lst)
        self.assertTrue(len(lst) == 2)

    def test_update_collection_for_sanity(self):
        '''
        Check if the update functionalities are implemented correctly.
        '''
        res1 = Resource('/foo/target', self.kind, [self.mixin], [])
        res2 = Resource('/foo/target', self.kind, [], [])
        workflow.update_collection(self.mixin, [res1], [res2], self.registry)
        self.assertTrue(self.mixin in res1.mixins)
        self.assertTrue(self.mixin in res2.mixins)

    def test_replace_collection_for_sanity(self):
        '''
        Check if the replace functionalities are implemented correctly.
        '''
        res1 = Resource('/foo/target', self.kind, [self.mixin], [])
        res2 = Resource('/foo/target', self.kind, [], [])
        workflow.replace_collection(self.mixin, [res1], [res2], self.registry)
        self.assertTrue(self.mixin not in res1.mixins)
        self.assertTrue(self.mixin in res2.mixins)

    def test_delete_from_collection_for_sanity(self):
        '''
        Check if the delete functionalities are implemented correctly.
        '''
        res1 = Resource('/foo/1', self.kind, [self.mixin], [])
        res2 = Resource('/foo/2', self.kind, [self.mixin], [])

        self.registry.add_resource('/foo/1', res1)
        self.registry.add_resource('/foo/2', res2)

        workflow.delete_from_collection(self.mixin, [res2], self.registry)
        self.assertTrue(self.mixin not in res2.mixins)
        self.assertTrue(self.mixin in res1.mixins)

    def test_filter_entities_for_sanity(self):
        '''
        Check if the filter operates correctly.
        '''
        # return all
        res = workflow.filter_entities(self.resources, [], {})
        self.assertTrue(self.resources[0] in res)
        self.assertTrue(self.resources[1] in res)
        self.assertTrue(self.resources[2] in res)
        self.assertTrue(len(res) == 3)

        # return just the two resources
        res = workflow.filter_entities(self.resources, [self.kind], {})
        self.assertTrue(self.resources[0] in res)
        self.assertTrue(self.resources[1] in res)
        self.assertTrue(len(res) == 2)

        # return source and link
        res = workflow.filter_entities(self.resources, [], {'foo': 'bar'})
        self.assertTrue(self.resources[0] in res)
        self.assertTrue(self.resources[2] in res)
        self.assertTrue(len(res) == 2)

        # return just the source
        res = workflow.filter_entities(self.resources, [self.mixin], {})
        self.assertTrue(self.resources[0] in res)
        self.assertTrue(len(res) == 1)

        # return just the source and link
        res = workflow.filter_entities(self.resources,
                                       [self.mixin, self.link_kind], {})
        self.assertTrue(self.resources[0] in res)
        self.assertTrue(self.resources[2] in res)
        self.assertTrue(len(res) == 2)

        # return just the link...
        res = workflow.filter_entities(self.resources, [self.kind],
                                       {'foo': 'bar'})
        self.assertTrue(self.resources[0] in res)
        self.assertTrue(len(res) == 1)
Exemplo n.º 18
0
class QueriyInterfaceTest(unittest.TestCase):
    '''
    Tests the QI routines.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.kind1 = Kind('http://www.example.com#', 'foo')
        self.kind2 = Kind('http://www.example.com#', 'bar')
        self.mixin = Mixin('http://www.example.com#', 'mixin')

        self.registry.set_backend(self.kind1, KindBackend())
        self.registry.set_backend(self.kind2, KindBackend())

    def tearDown(self):
        for item in self.registry.get_categories():
            self.registry.delete_mixin(item)

    #==========================================================================
    # Failure
    #==========================================================================

    def test_append_mixins_for_failure(self):
        '''
        Test if exception is thrown.
        '''
        # is not a mixin
        self.assertRaises(AttributeError, workflow.append_mixins, [self.kind2],
                          self.registry)

        # location collision
        mixin = Mixin('http://www.new.com#', 'mixin', location="/foo/")
        self.assertRaises(AttributeError, workflow.append_mixins, [mixin],
                          self.registry)

        # name collision
        mixin = Mixin('http://www.example.com#', 'foo', location="/stuff/")
        self.assertRaises(AttributeError, workflow.append_mixins, [mixin],
                          self.registry)

    def test_remove_mixins_for_failure(self):
        '''
        Test if only correct mixin get removed...
        '''
        mixin = Mixin('http://www.new.com#', 'mixin')
        self.registry.set_backend(mixin, MixinBackend())

        # not userdefined backend
        self.assertRaises(HTTPError, workflow.remove_mixins, [mixin],
                          self.registry)

        # not registeres
        self.assertRaises(HTTPError, workflow.remove_mixins, [self.mixin],
                          self.registry)

        # kind
        self.assertRaises(AttributeError, workflow.remove_mixins, [self.kind1],
                          self.registry)

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_filter_categories_for_sanity(self):
        '''
        Test the simple filter options.
        '''
        res = workflow.filter_categories([], self.registry)
        self.assertTrue(self.kind1 in res)
        self.assertTrue(self.kind2 in res)
        self.assertTrue(len(res) == 2)

        res = workflow.filter_categories([self.kind1], self.registry)
        self.assertTrue(self.kind1 in res)
        self.assertFalse(self.kind2 in res)
        self.assertTrue(len(res) == 1)

    def test_append_mixins_for_sanity(self):
        '''
        Test if mixins get appended.
        '''
        workflow.append_mixins([self.mixin], self.registry)
        self.assertTrue(self.mixin in self.registry.get_categories())
        self.assertTrue(
            isinstance(self.registry.get_backend(self.mixin), MixinBackend))

    def test_remove_mixins_for_sanity(self):
        '''
        Test if mixin get removed.
        '''
        workflow.append_mixins([self.mixin], self.registry)

        res = Resource('/foo/1', self.kind1, [self.mixin])
        self.registry.add_resource('/foo/1', res)

        workflow.remove_mixins([self.mixin], self.registry)
        self.assertFalse(self.mixin in self.registry.get_categories())
        self.assertFalse(self.mixin in res.mixins)
Exemplo n.º 19
0
class OCCI(object):
    '''
    A OCCI compatible service.
    '''

    # disabling 'Method could be func' pylint check (this is for extension)
    # pylint: disable=R0201

    def __init__(self, registry=None):

        if registry is None:
            self.registry = NonePersistentRegistry()
        elif isinstance(registry, Registry):
            self.registry = registry
        else:
            raise AttributeError('Registry needs to derive from abstract' \
                                 ' class \'Registry\'')

        self.registry.set_renderer('text/occi',
                                   TextOcciRendering(self.registry))
        self.registry.set_renderer('text/plain',
                                   TextPlainRendering(self.registry))
        self.registry.set_renderer('text/uri-list',
                                   TextUriListRendering(self.registry))
        self.registry.set_renderer('text/html', HTMLRendering(self.registry))

        application = tornado.web.Application([
            (r"/-/", QueryHandler, dict(registry=self.registry)),
            (r"/.well-known/org/ogf/occi/-/", QueryHandler,
             dict(registry=self.registry)),
            (r"(.*)/", CollectionHandler, dict(registry=self.registry)),
            (r"(.*)", ResourceHandler, dict(registry=self.registry)),
        ])

        self.http_server = tornado.httpserver.HTTPServer(application)

    def register_backend(self, category, backend):
        '''
        Register a backend.

        Verifies that correct 'parent' backends are used.

        category -- The category the backend defines.
        backend -- The backend which handles the given category.
        '''
        allow = False
        if repr(category) == 'kind' and isinstance(backend, KindBackend):
            allow = True
        elif repr(category) == 'mixin' and isinstance(backend, MixinBackend):
            allow = True
        elif repr(category) == 'action' and isinstance(backend, ActionBackend):
            allow = True

        if allow:
            self.registry.set_backend(category, backend)
        else:
            raise AttributeError('Backends handling kinds need to derive' \
                                 ' from KindBackend; Backends handling' \
                                 ' actions need to derive from' \
                                 ' ActionBackend and backends handling' \
                                 ' mixins need to derive from MixinBackend.')

    def start(self, port):
        '''
        Start the service.
        '''
        self.http_server.listen(port)
        tornado.ioloop.IOLoop.instance().start()
Exemplo n.º 20
0
class TestQueryCapabilites(unittest.TestCase):
    '''
    Test the QI.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.app = Application([(r"/-/", QueryWrapper)])
        self.registry.set_renderer('text/occi',
                                   TextOcciRendering(self.registry))

        backend = KindBackend()

        self.registry.set_backend(COMPUTE, backend)
        self.registry.set_backend(STORAGE, backend)
        self.registry.set_backend(NETWORK, backend)

    def tearDown(self):
        for item in self.registry.get_categories():
            self.registry.delete_mixin(item)

    #==========================================================================
    # Failure
    #==========================================================================

    def test_retrieval_for_failure(self):
        '''
        Tests failure handling on retrieval...
        '''
        # faulty accept header
        headers = {'Content-Type': 'text/occi', 'Category': 'sldkfj'}
        request = create_request('GET', headers, '')
        handler = QueryWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.get)

    def test_add_mixin_for_failure(self):
        '''
        Test failure handling off adding mixins.
        '''
        # missing locaction -> reject
        headers = {
            'Accept': 'text/occi',
            'Content-Type': 'text/occi',
            'Category': 'foo; scheme="http://example.com#"'
        }
        request = create_request('GET', headers, '')
        handler = QueryWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post)

        # existing location -> reject
        headers = {'Accept': 'text/occi',
                   'Content-Type': 'text/occi',
                   'Category': 'foo; scheme="http://example.com#";' \
                   ' location="/compute/"'}
        request = create_request('GET', headers, '')
        handler = QueryWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post)

        # faulty location -> reject
        headers = {'Accept': 'text/occi',
                   'Content-Type': 'text/occi',
                   'Category': 'foo; scheme="http://example.com#";' \
                   ' location="/sdf"'}
        request = create_request('GET', headers, '')
        handler = QueryWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post)

        # already existing...
        headers = {'Accept': 'text/occi',
                   'Content-Type': 'text/occi',
                   'Category': 'compute; scheme="http://schemas.ogf.org' \
                   '/occi/infrastructure#";' \
                   ' location="/bla/"'}
        request = create_request('GET', headers, '')
        handler = QueryWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post)

    def test_remove_mixin_for_failure(self):
        '''
        Test failure handling off removing mixins.
        '''
        # missing locaction -> reject
        headers = {
            'Accept': 'text/occi',
            'Content-Type': 'text/occi',
            'Category': 'foo; scheme="http://example.com#"'
        }
        request = create_request('DELETE', headers, '')
        handler = QueryWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.delete)

        # not available
        headers = {'Accept': 'text/occi',
                   'Content-Type': 'text/occi',
                   'Category': 'foo2; scheme="http://example.com#";' \
                   ' location="/foo/"'}
        request = create_request('DELETE', headers, '')
        handler = QueryWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.delete)

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_retrieval_for_sanity(self):
        '''
        Test HTTP GET on QI.
        '''
        # tests if all 3 kinds can be retrieved.
        headers = {'Accept': 'text/occi'}
        request = create_request('GET', headers, '')
        handler = QueryWrapper(self.app, request)
        handler.get()
        headers, body = handler.get_output()
        self.assertTrue(len(headers['Category'].split(',')) == 3)

        # test the filtering...
        headers = {
            'Accept': 'text/occi',
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE)
        }
        request = create_request('GET', headers, '')
        handler = QueryWrapper(self.app, request)
        handler.get()
        headers, body = handler.get_output()
        self.assertTrue(len(headers['Category'].split(',')) == 1)

    def test_mixin_for_sanity(self):
        '''
        Test if a user defined mixin can be added.
        '''
        # add a mixin.
        headers = {'Accept': 'text/occi',
                   'Content-Type': 'text/occi',
                   'Category': 'foo; scheme="http://example.com#";' \
                   ' location="/foo/"'}
        request = create_request('POST', headers, '')
        handler = QueryWrapper(self.app, request)
        handler.post()
        headers, body = handler.get_output()
        self.assertTrue(body == 'OK')

        # remove the mixin.
        headers = {'Accept': 'text/occi',
                   'Content-Type': 'text/occi',
                   'Category': 'foo; scheme="http://example.com#";' \
                   ' location="/foo/"'}
        request = create_request('DELETE', headers, '')
        handler = QueryWrapper(self.app, request)
        handler.delete()
        headers, body = handler.get_output()
        self.assertTrue(body == 'OK')
Exemplo n.º 21
0
class TestLinkHandling(unittest.TestCase):
    '''
    Tests links and do request in body for a change :-)
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.app = Application([(r"(.*)", ResourceWrapper)])
        self.registry.set_renderer('text/plain',
                                   TextPlainRendering(self.registry))
        self.registry.set_renderer('text/occi',
                                   TextOcciRendering(self.registry))

        self.registry.set_backend(COMPUTE, SimpleComputeBackend())
        self.registry.set_backend(NETWORK, KindBackend())
        self.registry.set_backend(NETWORKINTERFACE, KindBackend())
        self.registry.set_backend(START, SimpleComputeBackend())

        self.compute = Resource('/compute/1', COMPUTE, [])
        self.network = Resource('/network/1', NETWORK, [IPNETWORK])

        self.registry.add_resource('/compute/1', self.compute)
        self.registry.add_resource('/network/1', self.network)

    def tearDown(self):
        for item in self.registry.get_resources():
            self.registry.delete_resource(item.identifier)

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_inline_creation_for_sanity(self):
        '''
        Test creation of compute with a link to network (inline)...
        '''
        headers = {'Content-Type': 'text/occi',
                   'Category': parser.get_category_str(COMPUTE),
                   'Link': '</network/1>;' \
                   'rel="http://schemas.ogf.org/occi/infrastructure#' \
                   'network";' \
                   'category="http://schemas.ogf.org/occi/infrastructure#' \
                   'networkinterface";' \
                   'occi.networkinterface.interface="eth0";' \
                   'occi.networkinterface.mac="00:11:22:33:44:55";'}
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/2')
        self.assertTrue('/compute/2' in self.registry.get_resource_keys())
        self.assertTrue(len(self.registry.get_resources()) == 4)

        compute = self.registry.get_resource('/compute/2')
        self.assertTrue(len(compute.links) == 1)

        request = create_request('GET', {}, '')
        handler = ResourceWrapper(self.app, request)
        handler.get('/compute/2')
        heads, body = handler.get_output()
        self.assertTrue('Link: ' in body)
        self.assertTrue('self=' in body)

    def test_link_creation_for_sanity(self):
        '''
        Test creation for sanity...
        '''
        headers = {'Content-Type': 'text/plain'}
        body = 'Category: ' + parser.get_category_str(NETWORKINTERFACE) + '\n'
        body += 'X-OCCI-Attribute: occi.core.source="/compute/1"\n'
        body += 'X-OCCI-Attribute: occi.core.target="/network/1"'
        request = create_request('PUT', headers, body)
        handler = ResourceWrapper(self.app, request)
        handler.put('/link/2')
        self.assertTrue('/link/2' in self.registry.get_resource_keys())

        link = self.registry.get_resource('/link/2')
        self.assertTrue(link in link.source.links)

        request = create_request('GET', {}, '')
        handler = ResourceWrapper(self.app, request)
        handler.get('/link/2')
        heads, body = handler.get_output()
        self.assertTrue('occi.core.target' in body)
        self.assertTrue('occi.core.source' in body)
Exemplo n.º 22
0
class EntityWorkflowTest(unittest.TestCase):
    '''
    Simple tests to test the commands on entities.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.test_kind = Kind('http://example.com#', 'test')
        self.link_kind = Kind('http://example.com#link', 'link')
        mixins = []
        self.action = Action('http://example.com#', 'action')
        self.src_entity = Resource(None, self.test_kind, mixins, [])
        self.trg_entity = Resource('/foo/trg', self.test_kind, mixins, [])
        self.link1 = Link('/link/1', self.link_kind, [], self.src_entity,
                          self.trg_entity)
        self.src_entity.links = [self.link1]

        self.registry.add_resource(self.trg_entity.identifier, self.trg_entity)
        self.registry.set_backend(self.test_kind, KindBackend())
        self.registry.set_backend(self.link_kind, KindBackend())
        self.registry.set_backend(self.action, ActionBackend())

    def tearDown(self):
        for item in self.registry.get_resources():
            self.registry.delete_resource(item.identifier)

    #==========================================================================
    # Success
    #==========================================================================

    def test_replace_entity_for_success(self):
        '''
        Test replace...
        '''
        # not much to verify here - just calls backends...
        workflow.replace_entity(self.src_entity, self.trg_entity,
                                self.registry)

    def test_update_entity_for_success(self):
        '''
        Test replace...
        '''
        # not much to verify here - just calls backends...
        workflow.update_entity(self.src_entity, self.trg_entity, self.registry)

    def test_retrieve_entity_for_success(self):
        '''
        Test replace...
        '''
        # not much to verify here - just calls backends...
        workflow.retrieve_entity(self.src_entity, self.registry)
        workflow.retrieve_entity(self.link1, self.registry)

    def test_action_entity_for_success(self):
        '''
        Test replace...
        '''
        # not much to verify here - just calls backends...
        workflow.action_entity(self.src_entity, self.action, self.registry)
        workflow.action_entity(self.link1, self.action, self.registry)

    #==========================================================================
    # Failure
    #==========================================================================

    def test_create_resource_for_failure(self):
        '''
        Test if create behaves correct on faulty create calls...
        '''
        # the id of this link already exists...
        link2 = Link('/link/1', self.link_kind, [], self.src_entity,
                     self.trg_entity)
        self.src_entity.links.append(link2)
        self.assertRaises(AttributeError, workflow.create_entity, '/foo/bar',
                          self.src_entity, self.registry)

    def test_replace_entity_for_failure(self):
        '''
        Test replace for failure.
        '''
        self.trg_entity.links = [self.link1]
        # new entity should not have links...
        self.assertRaises(HTTPError, workflow.replace_entity, self.src_entity,
                          self.trg_entity, self.registry)

        # cannot replace reouce with link
        self.assertRaises(AttributeError, workflow.replace_entity,
                          self.src_entity, self.link1, self.registry)

    def test_update_entity_for_failure(self):
        '''
        Test update for failure.
        '''
        self.trg_entity.links = [self.link1]
        # new entity should not have links...
        self.assertRaises(HTTPError, workflow.update_entity, self.src_entity,
                          self.trg_entity, self.registry)

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_create_resource_link_ids_for_sanity(self):
        '''
        Test creation...
        '''
        # Check if an id get's set for the link...
        self.link1.identifier = None
        workflow.create_entity('/foo/src', self.src_entity, self.registry)
        self.assertTrue(self.link1.identifier is not None)

    def test_create_resource_for_sanity(self):
        '''
        Test creation...
        '''
        workflow.create_entity('/foo/src', self.src_entity, self.registry)
        # id needs to be set
        self.assertEqual(self.src_entity.identifier, '/foo/src')
        # entity needs to be available
        self.assertTrue(self.src_entity in self.registry.get_resources())
        # link entity needs to be available...
        self.assertTrue(self.link1 in self.registry.get_resources())
        self.assertTrue(len(self.src_entity.links) == 1)

    def test_create_link_for_sanity(self):
        '''
        Test creation...
        '''
        link2 = Link(None, self.link_kind, [], self.src_entity,
                     self.trg_entity)
        workflow.create_entity('/link/2', link2, self.registry)
        # id needs to be set
        self.assertEqual(link2.identifier, '/link/2')
        # entity needs to be available
        self.assertTrue(link2 in self.registry.get_resources())
        # link needs to be added to the src entity
        self.assertTrue(link2 in self.src_entity.links)
        self.assertTrue(len(self.src_entity.links) == 2)

    def test_delete_resource_for_sanity(self):
        '''
        Test deletion...
        '''
        workflow.create_entity('/foo/src', self.src_entity, self.registry)
        workflow.delete_entity(self.src_entity, self.registry)
        # ensure that both the resource and it's links are removed...
        self.assertFalse(self.src_entity in self.registry.get_resources())
        self.assertFalse(self.link1 in self.registry.get_resources())

    def test_delete_link_for_sanity(self):
        '''
        Test deletion...
        '''
        workflow.create_entity('/foo/src', self.src_entity, self.registry)
        workflow.delete_entity(self.link1, self.registry)
        self.assertFalse(self.link1 in self.src_entity.links)
        self.assertFalse(self.link1 in self.registry.get_resources())
Exemplo n.º 23
0
class TestParser(unittest.TestCase):
    '''
    Test for the parser.
    '''

    start_action = Action('http://schemas.ogf.org/occi/infrastructure#',
                          'start')
    compute = Kind('http://schemas.ogf.org/occi/infrastructure#',
                   'compute',
                   title='A OCCI compute...',
                   attributes={
                       'occi.compute.cores': '',
                       'occi.compute.state': 'immutable',
                       'occi.compute.memory': 'required'
                   },
                   related=[Resource.kind],
                   actions=[start_action])
    network_link = Kind('http://schemas.ogf.org/occi/infrastructure#',
                        'networkinterface',
                        related=[Link.kind])

    source = Resource('/1', compute, [])
    target = Resource('/2', compute, [])
    link1 = Link('/link/1', network_link, [], source, target)
    link2 = Link(None, network_link, [], source, target)

    registry = NonePersistentRegistry()

    def setUp(self):
        self.registry.add_resource(self.source.identifier, self.source)
        self.registry.add_resource(self.target.identifier, self.target)

        self.registry.set_backend(self.start_action, None)
        self.registry.set_backend(self.compute, None)
        self.registry.set_backend(self.network_link, None)

        self.link1.attributes = {'foo': 'bar'}

    def tearDown(self):
        for item in self.registry.get_categories():
            self.registry.delete_mixin(item)

    #==========================================================================
    # Success
    #==========================================================================

    def test_get_category_for_success(self):
        '''
        Tests if a mixin can be created.
        '''

        # disabling 'Method could be func' pylint check (pyunit fault :-))
        # pylint: disable=R0201

        # mixin check...
        tmp = 'foo; scheme="http://example.com#"; location="/foo_bar/"'
        parser.get_category(tmp, self.registry.get_categories(), is_mixin=True)

    #==========================================================================
    # Failure
    #==========================================================================

    def test_get_category_for_failure(self):
        '''
        Test with faulty category.
        '''
        self.assertRaises(AttributeError, parser.get_category, 'some crap',
                          self.registry.get_categories())
        self.assertRaises(AttributeError, parser.get_category,
                          'foo; scheme="bar"', self.registry.get_categories())

        # mixin with msg location check...
        tmp = 'foo; scheme="http://example.com#"'
        self.assertRaises(AttributeError, parser.get_category, tmp,
                          self.registry.get_categories(), True)

        # mixin with faulty location check...
        tmp = 'foo; scheme="http://example.com#"; location="sdf"'
        self.assertRaises(AttributeError, parser.get_category, tmp,
                          self.registry.get_categories(), True)

    def test_get_link_for_failure(self):
        '''
        Test with msg category.
        '''
        # no valid string...
        self.assertRaises(AttributeError, parser.get_link, 'some crap', None,
                          self.registry.get_categories())

        # no target...
        link_string = parser.get_link_str(self.link1)
        self.registry.delete_resource(self.target.identifier)
        self.assertRaises(AttributeError, parser.get_link, link_string, None,
                          self.registry)

    def test_get_attributes_for_failure(self):
        '''
        Verifies the parsing of attributes.
        '''
        self.assertRaises(AttributeError, parser.get_attributes, 'bla blub')

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_get_category_for_sanity(self):
        '''
        Simple sanity check...
        '''
        res = parser.get_category(parser.get_category_str(self.compute),
                                  self.registry.get_categories())
        self.assertEqual(res, self.compute)

    def test_get_link_for_sanity(self):
        '''
        Verifies that source and target are set...
        '''
        link_string = parser.get_link_str(self.link1)
        link = parser.get_link(link_string, self.source, self.registry)
        self.assertEquals(link.kind, self.network_link)
        self.assertEquals(link.source, self.source)
        self.assertEquals(link.target, self.target)
        # 4 = 1 attr + core.id + core.src + core.target
        self.assertTrue(len(link.attributes) == 4)

        # identifier checks...
        link_string = parser.get_link_str(self.link1)
        link = parser.get_link(link_string, self.source, self.registry)
        self.assertEquals(link.identifier, '/link/1')

        tmp = link_string.split('; ')
        tmp.pop(2)
        link_string = '; '.join(tmp)
        link = parser.get_link(link_string, self.source, self.registry)
        self.assertEquals(link.identifier, None)

    def test_strip_all_for_sanity(self):
        '''
        Tests if information get's stripped correctly.
        '''
        self.assertEqual('bla', parser._strip_all('bla'))
        self.assertEqual('bla', parser._strip_all('"bla"'))
        self.assertEqual('bla', parser._strip_all(' bla '))
        self.assertEqual('bla', parser._strip_all('"bla'))
        self.assertEqual('bla', parser._strip_all('bla" '))
        self.assertEqual('  bla', parser._strip_all('"  bla" '))
        self.assertEqual('some text', parser._strip_all('"some text" '))

    def test_get_attributes_for_sanity(self):
        '''
        Verifies the parsing of attributes.
        '''
        self.assertEquals(parser.get_attributes('foo=bar'), ('foo', 'bar'))
        self.assertEquals(parser.get_attributes('foo=bar '), ('foo', 'bar'))
        self.assertEquals(parser.get_attributes('foo= "some stuff"'),
                          ('foo', 'some stuff'))
        self.assertEquals(parser.get_attributes('foo = "bar"'), ('foo', 'bar'))
Exemplo n.º 24
0
class TestTextOcciRendering(unittest.TestCase):
    '''
    Simple sanity checks...
    '''

    # disable 'Unused attr' pylint check (not needing body here)
    # disable 'Too many instance attributes' pyling check (It's a test :))
    # pylint: disable=W0612,R0902

    registry = NonePersistentRegistry()

    def setUp(self):
        self.rendering = TextOcciRendering(self.registry)
        # type system...
        self.kind = Kind('http://example.com#', 'foo', related=[Resource.kind])
        self.invalid_kind = Kind('http://example.com#', 'invalid')
        self.link = Kind('http://example.com#', 'link', related=[Link.kind])
        self.mixin = Mixin('http://example.com#', 'mixin')
        self.action = Action('http://example.com#', 'action')

        self.registry.set_backend(self.kind, KindBackend())
        self.registry.set_backend(self.invalid_kind, KindBackend())
        self.registry.set_backend(self.link, KindBackend())
        self.registry.set_backend(self.mixin, MixinBackend())
        self.registry.set_backend(self.action, ActionBackend())

        # 2 linked entities
        self.entity = Resource('/foo/1', self.kind, [self.mixin])
        trg = Resource('/foo/2', self.kind, [], [])
        self.link1 = Link('/link/1', self.link, [], self.entity, trg)
        self.entity.links = [self.link1]

        self.registry.add_resource('/foo/2', trg)
        self.registry.add_resource('/link/1', self.link1)
        self.registry.add_resource('/foo/1', self.entity)

    def tearDown(self):
        for res in self.registry.get_resources():
            self.registry.delete_resource(res.identifier)
        for item in self.registry.get_categories():
            self.registry.delete_mixin(item)

    #==========================================================================
    # Failure
    #==========================================================================

    def test_resource_for_failure(self):
        '''
        Check if the correct exceptions are thrown.
        '''
        # no kind available...
        res = Resource('/foo/1', self.mixin, [], links=[])
        headers, body = self.rendering.from_entity(res)
        self.assertRaises(AttributeError, self.rendering.to_entity, headers,
                          body, None)

        # kind does not relate to link or resource...
        res.kind = self.invalid_kind
        headers, body = self.rendering.from_entity(res)
        self.assertRaises(AttributeError, self.rendering.to_entity, headers,
                          body, None)

    def test_resources_for_failure(self):
        '''
        Tests is a set of resource can be set and retrieved.
        '''
        heads = {'X-OCCI-Location': '/bla/bla/2'}
        self.assertRaises(AttributeError, self.rendering.to_entities, heads,
                          '')

    def test_link_for_failure(self):
        '''
        Test link...
        '''
        # call creation of entity with non existing trg resource.
        trg = Resource('/bar/1', self.kind, [], [])
        link = Link('/bar/1', self.link, [], self.entity, trg)
        headers, body = self.rendering.from_entity(link)
        self.assertRaises(AttributeError, self.rendering.to_entity, headers,
                          body, None)

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_resource_for_sanity(self):
        '''
        Test is a resource can be rendered and retrieved.
        '''
        # basic check
        headers, body = self.rendering.from_entity(self.entity)
        new = self.rendering.to_entity(headers, body, None)
        self.assertEqual(self.entity.kind, new.kind)
        self.assertEqual(len(self.entity.links), len(new.links))

        # verify that provided kind is taken
        kind = Kind('foo', 'bar', related=[Resource.kind])
        headers, body = self.rendering.from_entity(self.entity)
        new = self.rendering.to_entity(headers, body, kind)
        self.assertEqual(new.kind, kind)
        self.assertEqual(len(self.entity.links), len(new.links))

        # verify that actions get added
        self.entity.actions = [self.action]
        headers, body = self.rendering.from_entity(self.entity)
        self.assertTrue('?action' in headers['Link'])

    def test_resources_for_sanity(self):
        '''
        Tests is a set of resource can be set and retrieved for sanity.
        '''
        res = self.registry.get_resources()
        heads, body = self.rendering.from_entities(res, '/')
        entities = self.rendering.to_entities(heads, body)
        self.assertEqual(self.registry.get_resources(), entities)

    def test_link_for_sanity(self):
        '''
        Test is a link can be rendered and retrieved.
        '''
        headers, body = self.rendering.from_entity(self.link1)
        tmp = 'occi.core.target=' + self.link1.target.identifier
        tmp += ', occi.core.source=' + self.link1.source.identifier
        headers['X-OCCI-Attribute'] = tmp
        new = self.rendering.to_entity(headers, body, None)
        self.assertEqual(self.link1.kind, new.kind)
        # do not alter the source entity link list!
        self.assertTrue(len(self.entity.links) == 1)

    def test_qi_categories_for_sanity(self):
        '''
        Tests QI interface rendering...
        '''
        heads = {
            'Category':
            'foo; scheme="http://example.com#";' + ' location="/foo/"'
        }
        mixins = self.rendering.to_mixins(heads, '')
        headers, body = self.rendering.from_categories(mixins)
        self.assertTrue('foo' in headers['Category'])
        self.assertTrue('scheme="http://example.com#"' in headers['Category'])
        self.assertTrue('location="/foo/"' in headers['Category'])

    def test_action_for_sanity(self):
        '''
        Test the to actions function...
        '''
        heads = {
            'Category':
            self.action.term + '; scheme="' + self.action.scheme + '"'
        }
        action = self.rendering.to_action(heads, None)
        self.assertEqual(action, self.action)

    def test_get_filters_for_sanity(self):
        '''
        Test if filters can be retrieved...
        '''
        headers, body = self.rendering.from_categories([self.kind])
        cats, attrs = self.rendering.get_filters(headers, '')
        self.assertTrue(cats == [self.kind])
        self.assertTrue(attrs == {})

        headers['X-OCCI-Attribute'] = 'foo="bar"'
        cats, attrs = self.rendering.get_filters(headers, '')
        self.assertTrue(cats == [self.kind])
        self.assertTrue(attrs['foo'] == 'bar')
Exemplo n.º 25
0
class OCCI(object):
    '''
    A OCCI compatible service.
    '''

    # disabling 'Method could be func' pylint check (this is for extension)
    # pylint: disable=R0201

    def __init__(self, registry=None):

        if registry is None:
            self.registry = NonePersistentRegistry()
        elif isinstance(registry, Registry):
            self.registry = registry
        else:
            raise AttributeError('Registry needs to derive from abstract' \
                                 ' class \'Registry\'')

        self.registry.set_renderer('text/occi',
                                   TextOcciRendering(self.registry))
        self.registry.set_renderer('text/plain',
                                   TextPlainRendering(self.registry))
        self.registry.set_renderer('text/uri-list',
                                   TextUriListRendering(self.registry))
        self.registry.set_renderer('text/html', HTMLRendering(self.registry))

        application = tornado.web.Application([
                (r"/-/", QueryHandler, dict(registry=self.registry)),
                (r"/.well-known/org/ogf/occi/-/",
                 QueryHandler,
                 dict(registry=self.registry)),
                (r"(.*)/", CollectionHandler, dict(registry=self.registry)),
                (r"(.*)", ResourceHandler, dict(registry=self.registry)),
            ])

        self.http_server = tornado.httpserver.HTTPServer(application)

    def register_backend(self, category, backend):
        '''
        Register a backend.

        Verifies that correct 'parent' backends are used.

        category -- The category the backend defines.
        backend -- The backend which handles the given category.
        '''
        allow = False
        if repr(category) == 'kind' and isinstance(backend, KindBackend):
            allow = True
        elif repr(category) == 'mixin' and isinstance(backend, MixinBackend):
            allow = True
        elif repr(category) == 'action' and isinstance(backend, ActionBackend):
            allow = True

        if allow:
            self.registry.set_backend(category, backend)
        else:
            raise AttributeError('Backends handling kinds need to derive' \
                                 ' from KindBackend; Backends handling' \
                                 ' actions need to derive from' \
                                 ' ActionBackend and backends handling' \
                                 ' mixins need to derive from MixinBackend.')

    def start(self, port):
        '''
        Start the service.
        '''
        self.http_server.listen(port)
        tornado.ioloop.IOLoop.instance().start()
Exemplo n.º 26
0
class TestResourceCapabilites(unittest.TestCase):
    '''
    Test the Resource Handler.
    '''

    registry = NonePersistentRegistry()

    def setUp(self):
        self.app = Application([(r"(.*)", ResourceWrapper)])
        self.registry.set_renderer('text/occi',
                                   TextOcciRendering(self.registry))

        self.registry.set_backend(COMPUTE, SimpleComputeBackend())
        self.registry.set_backend(NETWORK, KindBackend())
        self.registry.set_backend(NETWORKINTERFACE, KindBackend())
        self.registry.set_backend(START, SimpleComputeBackend())

    def tearDown(self):
        for item in self.registry.get_resources():
            self.registry.delete_resource(item.identifier)

    #==========================================================================
    # Failure
    #==========================================================================

    def test_create_resource_for_failure(self):
        '''
        Put two resource and one link...
        '''
        headers = {'Content-Type': 'text/occi', 'Category': 'garbage'}
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.put, '/compute/1')

    def test_retrieve_resource_for_failure(self):
        '''
        test retrieval...
        '''
        headers = {'Accept': 'text/occi'}
        request = create_request('GET', headers, '')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.get, '/bla')

    def test_partial_update_for_failure(self):
        '''
        test update...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Attribute': 'occi.compute.cores="2"'
        }
        request = create_request('POST', headers, '')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post, '/bla')

        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE)
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')
        self.assertTrue('/compute/1' in self.registry.get_resource_keys())

        headers = {'Content-Type': 'text/occi', 'X-Occi-Attribute': 'garbage'}
        request = create_request('POST', headers, '')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post, '/compute/1')

    def test_replace_for_failure(self):
        '''
        test update...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE),
            'X-Occi-Attribute': 'occi.compute.memory="2.0"'
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')
        self.assertTrue('/compute/1' in self.registry.get_resource_keys())

        headers = {'Content-Type': 'text/occi', 'Category': 'garbage'}
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.put, '/compute/1')

    def test_delete_for_failure(self):
        '''
        Test delete...
        '''
        request = create_request('DELETE', {}, '')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.delete, '/compute/2')

        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE),
            'X-Occi-Attribute': 'undeletable="true"'
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')
        self.assertTrue('/compute/1' in self.registry.get_resource_keys())

        request = create_request('DELETE', {}, '')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.delete, '/compute/1')

    def test_trigger_action_for_failure(self):
        '''
        Trigger an action...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE)
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/3')
        self.assertTrue('/compute/3' in self.registry.get_resource_keys())

        headers = {'Content-Type': 'text/occi', 'Category': 'blabla'}
        request = create_request('POST', headers, '', '/compute/3?action=' \
                                 'start')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post, '/compute/3')

        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(START)
        }
        request = create_request('POST', headers, '', '/compute/3?action=' \
                                 'start')
        handler = ResourceWrapper(self.app, request)
        self.assertRaises(HTTPError, handler.post, '/bla"')

    #==========================================================================
    # Sanity
    #==========================================================================

    def test_create_resource_for_sanity(self):
        '''
        Put two resource and one link...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE)
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')
        self.assertTrue('/compute/1' in self.registry.get_resource_keys())

        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(NETWORK)
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/network/1')
        self.assertTrue('/network/1' in self.registry.get_resource_keys())

        headers = {'Content-Type': 'text/occi',
                   'Category': parser.get_category_str(NETWORKINTERFACE),
                   'X-Occi-Attribute': 'occi.core.source="/compute/1",' \
                                       ' occi.core.target="/network/1"'}
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/network/link/1')
        self.assertTrue('/network/link/1' in self.registry.get_resource_keys())
        compute = self.registry.get_resource('/compute/1')
        self.assertTrue(len(compute.links) == 1)
        heads, body = handler.get_output()
        self.assertTrue('/network/link/1' in heads['Location'])

    def test_retrieve_resource_for_sanity(self):
        '''
        test retrieval...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE)
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')
        self.assertTrue('/compute/1' in self.registry.get_resource_keys())

        headers = {'Accept': 'text/occi'}
        request = create_request('GET', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.get('/compute/1')
        heads, body = handler.get_output()
        self.assertTrue('"/compute/1"' in heads['X-OCCI-Attribute'])
        self.assertTrue('compute' in heads['Category'])
        self.assertTrue('text/occi' in heads['Content-Type'])

    def test_partial_update_for_sanity(self):
        '''
        test update...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE)
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')
        self.assertTrue('/compute/1' in self.registry.get_resource_keys())

        headers = {
            'Content-Type': 'text/occi',
            'X-Occi-Attribute': 'occi.compute.cores="2"'
        }
        request = create_request('POST', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.post('/compute/1')

        compute = self.registry.get_resource('/compute/1')
        self.assertTrue('occi.compute.cores' in compute.attributes.keys())
        heads, body = handler.get_output()

    def test_replace_for_sanity(self):
        '''
        test update...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE),
            'X-Occi-Attribute': 'occi.compute.memory="2.0"'
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')
        self.assertTrue('/compute/1' in self.registry.get_resource_keys())

        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE),
            'X-Occi-Attribute': 'occi.compute.cores="2"'
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')

        compute = self.registry.get_resource('/compute/1')
        self.assertTrue('occi.compute.memory' not in compute.attributes.keys())
        self.assertTrue('occi.compute.cores' in compute.attributes.keys())

        heads, body = handler.get_output()

    def test_delete_for_sanity(self):
        '''
        Test delete...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE),
            'X-Occi-Attribute': 'occi.compute.memory="2.0"'
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/1')
        self.assertTrue('/compute/1' in self.registry.get_resource_keys())

        request = create_request('DELETE', {}, '')
        handler = ResourceWrapper(self.app, request)
        handler.delete('/compute/1')
        self.assertTrue('/compute/1' not in self.registry.get_resource_keys())

    def test_trigger_action_for_sanity(self):
        '''
        Trigger an action...
        '''
        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(COMPUTE)
        }
        request = create_request('PUT', headers, '')
        handler = ResourceWrapper(self.app, request)
        handler.put('/compute/3')
        self.assertTrue('/compute/3' in self.registry.get_resource_keys())

        headers = {
            'Content-Type': 'text/occi',
            'Category': parser.get_category_str(START)
        }
        request = create_request('POST', headers, '', '/compute/3?action' \
                                 '=start')
        handler = ResourceWrapper(self.app, request)
        handler.post('/compute/3')

        compute = self.registry.get_resource('/compute/3')
        self.assertTrue(compute.attributes['occi.compute.state'] == 'active')
Exemplo n.º 27
0
class BaseHandler(tornado.web.RequestHandler):
    '''
    General request handler.
    '''

    def initialize(self, registry):
        self.registry = registry
        if self.registry.get_hostname() == '':
            self.registry.set_hostname(self.request.protocol + '://' +
                                       self.request.host)

    def __init__(self, application, request, **kwargs):
        super(BaseHandler, self).__init__(application, request, **kwargs)
        # This ensures that at least one registry is loaded in case initialize
        # is not called for some reason...
        self.registry = NonePersistentRegistry()

        if self.registry.get_hostname() == '':
            self.registry.set_hostname(self.request.protocol + '://' +
                                       self.request.host)

    def extract_http_data(self):
        '''
        Extracts all necessary information from the HTTP envelop. Minimize the
        data which is carried around inside of the service. Also ensures that
        the names are always equal - When deployed in Apache the names of the
        Headers change.
        '''
        heads = {}
        headers = self.request.headers
        if 'Category' in headers:
            heads['Category'] = headers['Category']
        if 'X-Occi-Attribute' in headers:
            heads['X-OCCI-Attribute'] = headers['X-Occi-Attribute']
        if 'X-Occi-Location' in headers:
            heads['X-OCCI-Location'] = headers['X-Occi-Location']
        if 'Link' in headers:
            heads['Link'] = headers['Link']
        if self.request.body is not '':
            body = self.request.body.strip()
        else:
            body = ''

        return heads, body

    def get_renderer(self, content_type):
        '''
        Returns the proper rendering parser.

        content_type -- String with either either Content-Type or Accept.
        '''
        try:
            return self.registry.get_renderer(
                                            self.request.headers[content_type])
        except KeyError:
            return self.registry.get_renderer(self.registry.get_default_type())

    def response(self, status, mime_type, headers, body='OK'):
        '''
        Will create a response and send it to the client.

        status -- The status code.
        mime_type -- Sets the Content-Type of the response.
        headers -- The HTTP headers.
        body -- The text for the body (default: ok).
        '''
        self.set_header('Server', VERSION)
        self.set_header('Content-Type', mime_type)
        self.set_status(status)
        if headers is not None:
            for item in headers.keys():
                self._headers[item] = headers[item]
        self.write(body)
        self.finish('\n')

    def get_error_html(self, status_code, **kwargs):
        self.set_header('Server', VERSION)
        self.set_header('Content-Type', self.registry.get_default_type())
        exception = sys.exc_info()[1]
        msg = str(exception)
        self.set_status(status_code)
        return msg

    def parse_action(self):
        '''
        Retrieves the Action which was given in the request.
        '''
        headers, body = self.extract_http_data()
        rendering = self.get_renderer(CONTENT_TYPE)

        action = rendering.to_action(headers, body)

        return action

    def parse_filter(self):
        '''
        Retrieve any attributes or categories which where provided in the
        request for filtering.
        '''
        headers, body = self.extract_http_data()

        attr = 'X-OCCI-Attribute'
        if  attr not in headers and 'Category' not in headers and body == '':
            return [], {}

        rendering = self.get_renderer(CONTENT_TYPE)

        categories, attributes = rendering.get_filters(headers, body)

        return categories, attributes

    def parse_entity(self, def_kind=None):
        '''
        Retrieves the entity which was rendered within the request.

        def_kind -- Indicates if the request can be incomplete (False).
        '''
        headers, body = self.extract_http_data()
        rendering = self.get_renderer(CONTENT_TYPE)

        entity = rendering.to_entity(headers, body, def_kind)

        return entity

    def parse_entities(self):
        '''
        Retrieves a set of entities which was rendered within the request.
        '''
        headers, body = self.extract_http_data()
        rendering = self.get_renderer(CONTENT_TYPE)

        entities = rendering.to_entities(headers, body)

        return entities

    def parse_mixins(self):
        '''
        Retrieves a mixin from a request.
        '''
        headers, body = self.extract_http_data()
        rendering = self.get_renderer(CONTENT_TYPE)

        mixin = rendering.to_mixins(headers, body)

        return mixin

    def render_entity(self, entity):
        '''
        Renders a single entity to the client.

        entity -- The entity which should be rendered.
        '''
        rendering = self.get_renderer(ACCEPT)

        headers, body = rendering.from_entity(entity)

        self.response(200, rendering.mime_type, headers, body)

    def render_entities(self, entities, key):
        '''
        Renders a list of entities to the client.

        entities -- The entities which should be rendered.
        '''
        rendering = self.get_renderer(ACCEPT)

        headers, body = rendering.from_entities(entities, key)

        self.response(200, rendering.mime_type, headers, body)

    def render_categories(self, categories):
        '''
        Renders a list of categories to the client.

        categories -- The categories which should be rendered.
        '''
        rendering = self.get_renderer(ACCEPT)

        headers, body = rendering.from_categories(categories)

        self.response(200, rendering.mime_type, headers, body)