summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortermie <github@anarkystic.com>2011-03-24 12:42:46 -0700
committertermie <github@anarkystic.com>2011-03-24 12:42:46 -0700
commitef5c9e11595a00de468783adbb60cfbc2cbbf13d (patch)
treea4ff720fb7bbbd4dd74eca4ae24950e2bf0c2449
parentac44b8a9c5ed6a761793e1fa997768bd00a6c2da (diff)
downloadnova-ef5c9e11595a00de468783adbb60cfbc2cbbf13d.tar.gz
nova-ef5c9e11595a00de468783adbb60cfbc2cbbf13d.tar.xz
nova-ef5c9e11595a00de468783adbb60cfbc2cbbf13d.zip
add Limited, an API limiting/versioning wrapper
-rwxr-xr-xbin/nova-direct-api7
-rw-r--r--nova/api/direct.py36
2 files changed, 43 insertions, 0 deletions
diff --git a/bin/nova-direct-api b/bin/nova-direct-api
index 1a78fb0c0..ac0b5b51c 100755
--- a/bin/nova-direct-api
+++ b/bin/nova-direct-api
@@ -53,12 +53,19 @@ flags.DEFINE_flag(flags.HelpXMLFlag())
+class ReadOnlyCompute(direct.Limited):
+ """Read-only Compute API."""
+
+ _allowed = ['get', 'get_all', 'get_console_output']
+
+
if __name__ == '__main__':
utils.default_flagfile()
FLAGS(sys.argv)
logging.setup()
direct.register_service('compute', compute.API())
+ direct.register_service('compute-readonly', ReadOnlyCompute(compute.API()))
direct.register_service('volume', volume.API())
direct.register_service('network', network.API())
direct.register_service('reflect', direct.Reflection())
diff --git a/nova/api/direct.py b/nova/api/direct.py
index dfca250e0..1011091a6 100644
--- a/nova/api/direct.py
+++ b/nova/api/direct.py
@@ -211,6 +211,42 @@ class ServiceWrapper(wsgi.Controller):
return result
+class Limited(object):
+ __notdoc = """Limit the available methods on a given object.
+
+ (Not a docstring so that the docstring can be conditionally overriden.)
+
+ Useful when defining a public API that only exposes a subset of an
+ internal API.
+
+ Expected usage of this class is to define a subclass that lists the allowed
+ methods in the 'allowed' variable.
+
+ Additionally where appropriate methods can be added or overwritten, for
+ example to provide backwards compatibility.
+
+ """
+
+ _allowed = None
+
+ def __init__(self, proxy):
+ self._proxy = proxy
+ if not self.__doc__:
+ self.__doc__ = proxy.__doc__
+ if not self._allowed:
+ self._allowed = []
+
+ def __getattr__(self, key):
+ """Only return methods that are named in self._allowed."""
+ if key not in self._allowed:
+ raise AttributeError()
+ return getattr(self._proxy, key)
+
+ def __dir__(self):
+ """Only return methods that are named in self._allowed."""
+ return [x for x in dir(self._proxy) if x in self._allowed]
+
+
class Proxy(object):
"""Pretend a Direct API endpoint is an object."""
def __init__(self, app, prefix=None):