[PATCH V4 0/4] improve controller

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> V3 -> V4 rebase fix typo move the improvement function from src/kimchi/utils.py to src/kimchi/control/utils.py V2 -> V3 use the CapWords convention to name class name. add the import statement in alphabetical order use __import__ to import the moudle instead of imp.load_module imp.load_module does more than importing the module: if the module was already imported, it is equivalent to a reload()! we can use the imp.load_module as follow: try: module = sys.modules[module_name] except KeyError: mod_fobj, mod_absp, mod_desc = imp.find_module(mod_name, [path]) module = imp.load_module(module_name, mod_fobj, mod_absp, mod_desc) V1 -> V2 fix typo. remove print use url_auth instead of _url_sub_node_auth improve the commit description add a method to load root sub collections/resouces automatically ShaoHe Feng (4): improve controller: add a method to load root sub collections/resouces automatically improve controller: tag the collections/resouces of root with @UrlSubNode improve controller: Root loads collections/resouces automatically improve controller: set authentication automatically src/kimchi/control/__init__.py | 8 ++++++++ src/kimchi/control/config.py | 2 ++ src/kimchi/control/debugreports.py | 2 ++ src/kimchi/control/host.py | 2 ++ src/kimchi/control/interfaces.py | 2 ++ src/kimchi/control/networks.py | 2 ++ src/kimchi/control/plugins.py | 2 ++ src/kimchi/control/storagepools.py | 2 ++ src/kimchi/control/tasks.py | 2 ++ src/kimchi/control/templates.py | 2 ++ src/kimchi/control/utils.py | 39 ++++++++++++++++++++++++++++++++++++++ src/kimchi/control/vms.py | 3 ++- src/kimchi/root.py | 28 +++++---------------------- src/kimchi/server.py | 12 +++++------- 14 files changed, 77 insertions(+), 31 deletions(-) -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> load_url_sub_node can load collections/resouces automatically when they are tagged with @UrlSubNode Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/utils.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/kimchi/control/utils.py b/src/kimchi/control/utils.py index 814ba20..2dd351c 100644 --- a/src/kimchi/control/utils.py +++ b/src/kimchi/control/utils.py @@ -25,12 +25,14 @@ import cherrypy import json +import os from jsonschema import Draft3Validator, ValidationError, FormatChecker from kimchi.exception import InvalidParameter +from kimchi.utils import import_module def get_class_name(cls): @@ -103,3 +105,40 @@ def validate_params(params, instance, action): except ValidationError: raise InvalidParameter('; '.join( e.message for e in validator.iter_errors(request))) + + +class UrlSubNode(object): + def __init__(self, name, auth=False): + self.name = name + self.auth = auth + + def __call__(self, fun): + fun._url_sub_node_name = {"name": self.name} + fun.url_auth = self.auth + return fun + + +def listPathModules(path): + modules = set() + for f in os.listdir(path): + base, ext = os.path.splitext(f) + if ext in ('.py', '.pyc', '.pyo'): + modules.add(base) + return sorted(modules) + + +def load_url_sub_node(path, package_name, expect_attr="_url_sub_node_name"): + sub_nodes = {} + for mod_name in listPathModules(path): + if mod_name.startswith("_"): + continue + + module = import_module(package_name + '.' + mod_name) + + for node in [getattr(module, x) for x in dir(module)]: + if not hasattr(node, expect_attr): + continue + name = getattr(node, expect_attr)["name"] + sub_nodes.update({name: node}) + + return sub_nodes -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> we can difine a /host as follow: @UrlSubNode("host", True) class Host(Resource): def __init__(self, model, id=None): super(Host, self).__init__(model, id) @UrlSubNode("host", True) means: the URL "/host" is root.Host, and it need authentication Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/__init__.py | 8 ++++++++ src/kimchi/control/config.py | 2 ++ src/kimchi/control/debugreports.py | 2 ++ src/kimchi/control/host.py | 2 ++ src/kimchi/control/interfaces.py | 2 ++ src/kimchi/control/networks.py | 2 ++ src/kimchi/control/plugins.py | 2 ++ src/kimchi/control/storagepools.py | 2 ++ src/kimchi/control/tasks.py | 2 ++ src/kimchi/control/templates.py | 2 ++ src/kimchi/control/vms.py | 3 ++- 11 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/kimchi/control/__init__.py b/src/kimchi/control/__init__.py index 8a37cc4..f24f9f3 100644 --- a/src/kimchi/control/__init__.py +++ b/src/kimchi/control/__init__.py @@ -19,3 +19,11 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import os + + +from kimchi.control.utils import load_url_sub_node + + +sub_nodes = load_url_sub_node(os.path.dirname(__file__), __name__) diff --git a/src/kimchi/control/config.py b/src/kimchi/control/config.py index 603f51d..cc41e8a 100644 --- a/src/kimchi/control/config.py +++ b/src/kimchi/control/config.py @@ -27,8 +27,10 @@ import cherrypy from kimchi.config import config from kimchi.control.base import Collection, Resource +from kimchi.control.utils import UrlSubNode +@UrlSubNode("config") class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) diff --git a/src/kimchi/control/debugreports.py b/src/kimchi/control/debugreports.py index a55ba38..324d826 100644 --- a/src/kimchi/control/debugreports.py +++ b/src/kimchi/control/debugreports.py @@ -23,8 +23,10 @@ from kimchi.control.base import AsyncCollection, Resource from kimchi.control.utils import internal_redirect +from kimchi.control.utils import UrlSubNode +@UrlSubNode("debugreports", True) class DebugReports(AsyncCollection): def __init__(self, model): super(DebugReports, self).__init__(model) diff --git a/src/kimchi/control/host.py b/src/kimchi/control/host.py index 9b19577..f041b35 100644 --- a/src/kimchi/control/host.py +++ b/src/kimchi/control/host.py @@ -24,8 +24,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from kimchi.control.base import Collection, Resource +from kimchi.control.utils import UrlSubNode +@UrlSubNode("host", True) class Host(Resource): def __init__(self, model, id=None): super(Host, self).__init__(model, id) diff --git a/src/kimchi/control/interfaces.py b/src/kimchi/control/interfaces.py index 28be26e..f93dd6a 100644 --- a/src/kimchi/control/interfaces.py +++ b/src/kimchi/control/interfaces.py @@ -23,8 +23,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from kimchi.control.base import Collection, Resource +from kimchi.control.utils import UrlSubNode +@UrlSubNode("interfaces") class Interfaces(Collection): def __init__(self, model): super(Interfaces, self).__init__(model) diff --git a/src/kimchi/control/networks.py b/src/kimchi/control/networks.py index f3f0b41..8510e49 100644 --- a/src/kimchi/control/networks.py +++ b/src/kimchi/control/networks.py @@ -22,8 +22,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from kimchi.control.base import Collection, Resource +from kimchi.control.utils import UrlSubNode +@UrlSubNode("networks", True) class Networks(Collection): def __init__(self, model): super(Networks, self).__init__(model) diff --git a/src/kimchi/control/plugins.py b/src/kimchi/control/plugins.py index af32709..5938085 100644 --- a/src/kimchi/control/plugins.py +++ b/src/kimchi/control/plugins.py @@ -25,8 +25,10 @@ import kimchi.template from kimchi.control.base import Collection, Resource from kimchi.control.utils import get_class_name, model_fn +from kimchi.control.utils import UrlSubNode +@UrlSubNode("plugins") class Plugins(Collection): def __init__(self, model): super(Plugins, self).__init__(model) diff --git a/src/kimchi/control/storagepools.py b/src/kimchi/control/storagepools.py index 35e7664..3b8ef79 100644 --- a/src/kimchi/control/storagepools.py +++ b/src/kimchi/control/storagepools.py @@ -31,8 +31,10 @@ from kimchi.control.storagevolumes import IsoVolumes, StorageVolumes from kimchi.control.utils import get_class_name, model_fn, parse_request from kimchi.control.utils import validate_params from kimchi.model import ISO_POOL_NAME +from kimchi.control.utils import UrlSubNode +@UrlSubNode("storagepools", True) class StoragePools(Collection): def __init__(self, model): super(StoragePools, self).__init__(model) diff --git a/src/kimchi/control/tasks.py b/src/kimchi/control/tasks.py index b799422..f3dbfd9 100644 --- a/src/kimchi/control/tasks.py +++ b/src/kimchi/control/tasks.py @@ -22,8 +22,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from kimchi.control.base import Collection, Resource +from kimchi.control.utils import UrlSubNode +@UrlSubNode("tasks", True) class Tasks(Collection): def __init__(self, model): super(Tasks, self).__init__(model) diff --git a/src/kimchi/control/templates.py b/src/kimchi/control/templates.py index a77936e..ce1dda4 100644 --- a/src/kimchi/control/templates.py +++ b/src/kimchi/control/templates.py @@ -22,8 +22,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from kimchi.control.base import Collection, Resource +from kimchi.control.utils import UrlSubNode +@UrlSubNode("templates", True) class Templates(Collection): def __init__(self, model): super(Templates, self).__init__(model) diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py index 7843be7..a7a0b3b 100644 --- a/src/kimchi/control/vms.py +++ b/src/kimchi/control/vms.py @@ -23,9 +23,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from kimchi.control.base import Collection, Resource -from kimchi.control.utils import internal_redirect +from kimchi.control.utils import internal_redirect, UrlSubNode +@UrlSubNode("vms", True) class VMs(Collection): def __init__(self, model): super(VMs, self).__init__(model) -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Remove hard code from root.py. We do not need to touch root.py any more when we add a new sub collection/resouce. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/root.py | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index 8d4f92a..83a777c 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -28,24 +28,15 @@ import json from kimchi import auth from kimchi import template from kimchi.config import get_api_schema_file +from kimchi.control import sub_nodes from kimchi.control.base import Resource -from kimchi.control.config import Config -from kimchi.control.debugreports import DebugReports -from kimchi.control.host import Host -from kimchi.control.interfaces import Interfaces -from kimchi.control.networks import Networks -from kimchi.control.plugins import Plugins -from kimchi.control.storagepools import StoragePools -from kimchi.control.storageservers import StorageServers -from kimchi.control.tasks import Tasks -from kimchi.control.templates import Templates from kimchi.control.utils import parse_request -from kimchi.control.vms import VMs from kimchi.exception import OperationFailed class Root(Resource): def __init__(self, model, dev_env): + super(Root, self).__init__(model) self._handled_error = ['error_page.400', 'error_page.404', 'error_page.405', 'error_page.406', 'error_page.415', 'error_page.500'] @@ -57,18 +48,9 @@ class Root(Resource): self._cp_config = dict([(key, self.error_development_handler) for key in self._handled_error]) - Resource.__init__(self, model) - self.vms = VMs(model) - self.templates = Templates(model) - self.storagepools = StoragePools(model) - self.storageservers = StorageServers(model) - self.interfaces = Interfaces(model) - self.networks = Networks(model) - self.tasks = Tasks(model) - self.config = Config(model) - self.host = Host(model) - self.debugreports = DebugReports(model) - self.plugins = Plugins(model) + for ident, node in sub_nodes.items(): + setattr(self, ident, node(model)) + self.api_schema = json.load(open(get_api_schema_file())) def error_production_handler(self, status, message, traceback, version): -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Remove hard code from server.py. We do not need to touch server.py any more when we add a new sub collection/resouce. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/server.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/kimchi/server.py b/src/kimchi/server.py index b820263..2a9f53f 100644 --- a/src/kimchi/server.py +++ b/src/kimchi/server.py @@ -33,6 +33,7 @@ from kimchi import config from kimchi import model from kimchi import mockmodel from kimchi import vnc +from kimchi.control import sub_nodes from kimchi.root import Root from kimchi.utils import get_enabled_plugins, import_class @@ -74,13 +75,6 @@ class Server(object): 'tools.sessions.storage_type': 'file', 'tools.sessions.storage_path': config.get_session_path(), 'tools.kimchiauth.on': False}, - '/host': {'tools.kimchiauth.on': True}, - '/vms': {'tools.kimchiauth.on': True}, - '/templates': {'tools.kimchiauth.on': True}, - '/networks': {'tools.kimchiauth.on': True}, - '/storagepools': {'tools.kimchiauth.on': True}, - '/tasks': {'tools.kimchiauth.on': True}, - '/debugreports': {'tools.kimchiauth.on': True}, '/css': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'ui/css', @@ -193,6 +187,10 @@ class Server(object): vnc_ws_proxy = vnc.new_ws_proxy() cherrypy.engine.subscribe('exit', vnc_ws_proxy.kill) + for ident, node in sub_nodes.items(): + if node.url_auth: + self.configObj["/%s" % ident] = {'tools.kimchiauth.on': True} + self.app = cherrypy.tree.mount(Root(model_instance, dev_env), config=self.configObj) self._load_plugins() -- 1.8.4.2

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> Tested-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 01/23/2014 11:38 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
V3 -> V4 rebase fix typo move the improvement function from src/kimchi/utils.py to src/kimchi/control/utils.py
V2 -> V3 use the CapWords convention to name class name. add the import statement in alphabetical order
use __import__ to import the moudle instead of imp.load_module imp.load_module does more than importing the module: if the module was already imported, it is equivalent to a reload()!
we can use the imp.load_module as follow: try: module = sys.modules[module_name] except KeyError: mod_fobj, mod_absp, mod_desc = imp.find_module(mod_name, [path]) module = imp.load_module(module_name, mod_fobj, mod_absp, mod_desc)
V1 -> V2 fix typo. remove print use url_auth instead of _url_sub_node_auth improve the commit description
add a method to load root sub collections/resouces automatically
ShaoHe Feng (4): improve controller: add a method to load root sub collections/resouces automatically improve controller: tag the collections/resouces of root with @UrlSubNode improve controller: Root loads collections/resouces automatically improve controller: set authentication automatically
src/kimchi/control/__init__.py | 8 ++++++++ src/kimchi/control/config.py | 2 ++ src/kimchi/control/debugreports.py | 2 ++ src/kimchi/control/host.py | 2 ++ src/kimchi/control/interfaces.py | 2 ++ src/kimchi/control/networks.py | 2 ++ src/kimchi/control/plugins.py | 2 ++ src/kimchi/control/storagepools.py | 2 ++ src/kimchi/control/tasks.py | 2 ++ src/kimchi/control/templates.py | 2 ++ src/kimchi/control/utils.py | 39 ++++++++++++++++++++++++++++++++++++++ src/kimchi/control/vms.py | 3 ++- src/kimchi/root.py | 28 +++++---------------------- src/kimchi/server.py | 12 +++++------- 14 files changed, 77 insertions(+), 31 deletions(-)
participants (2)
-
Aline Manera
-
shaohef@linux.vnet.ibm.com